Positions and sizes are fixed in the example, but TGUI also supports relative positions/sizes:
editBoxUsername.SetSize(new TGUI.Layout2d("65%", "12.5%"));
using System;
using SFML.Window;
using SFML.Graphics;
using System.Collections.Generic;
namespace TGUI.Example
{
class Example
{
static TGUI.EditBox? editBoxUsername = null;
static TGUI.EditBox? editBoxPassword = null;
const uint width = 400;
const uint height = 300;
static void CreateWidgets(Gui gui)
{
// TGUI objects should be disposed when you no longer need them in C# to reduce memory usage.
// This can be done by calling "widget.Dispose()" or doing it automatically when the object
// goes out of scope by making use of the "using" keyword.
// Note that disposing only releases the C# handle. The internal c++ code relies on reference counting
// to determine when an object is destroyed. Adding the widget to the gui added another reference,
// so the widget will continue to exist internally until it is also removed from the gui.
// If the C# object isn't disposed then a reference remains until the garbage collector finalizes the C# object.
using var texture = new TGUI.Texture("background.jpg");
using var picture = new TGUI.Picture();
picture.Renderer.Texture = texture;
picture.SetSize(new TGUI.Vector2f(width, height));
gui.Add(picture, "PictureBackground");
// We don't use "using" here because we still need the edit boxes in our button callback
// after this function has finished executing. If the code contained "using var", the C# object
// would be destroyed at the end of this function. While the edit box continues to exist in the gui,
// we could no longer access it with our C# object (unless we get a new reference with gui.Get("EditUsername")).
editBoxUsername = new EditBox();
editBoxUsername.SetPosition(new Vector2f(width / 6, height / 6));
editBoxUsername.SetSize(new Vector2f(width * 2/3, height / 8));
editBoxUsername.DefaultText = "Username";
gui.Add(editBoxUsername, "EditUsername");
editBoxPassword = new EditBox(editBoxUsername);
editBoxPassword.SetPosition(new Vector2f(width / 6, height * 5/12));
editBoxPassword.PasswordCharacter = "*";
editBoxPassword.DefaultText = "Password";
gui.Add(editBoxPassword, "EditPassword");
using var button = new Button();
button.Text = "Login";
button.SetPosition(new Vector2f(width / 4, height * 7/10));
button.SetSize(new Vector2f(width / 2, height / 6));
gui.Add(button, "ButtonLogin");
// Print the values of the edit boxes when the login button is pressed.
// The editBoxUsername and editBoxPassword variables should not have been disposed
// by the time the user presses the button, or attempting to access them will throw.
button.OnPress += (_,_) => Console.WriteLine("Username: " + editBoxUsername.Text + "\n"
+ "Password: " + editBoxPassword.Text);
}
static void Main(string[] args)
{
var window = new RenderWindow(new VideoMode(width, height), "TGUI.Net example");
window.Closed += (_,e) => window.Close();
// The first TGUI object to create should always be the Gui.
// Other TGUI objects should only be used while a gui exists.
var gui = new TGUI.Gui(window);
// We create the widgets in a separate function in this example to demonstrate that
// the widgets don't need to be stored in C# in order for them to be part of the gui.
CreateWidgets(gui);
while (window.IsOpen)
{
window.DispatchEvents();
window.Clear();
gui.Draw();
window.Display();
}
// Cleanup TGUI resources. This isn't really needed here since this is the end of the program,
// but the purpose of the example is to show how to properly do this. Note that if TGUI objects aren't disposed,
// the same cleanup code will be executed by the finalizer. Disposing explicitly can reduce memory usage though,
// mostly because the garbage collector doesn't know about the large amount of unmanaged c++ memory being reserved
// until the lightweight C# object is destroyed. So the garbage collector can let objects linger around too long.
// The other widgets were already disposed in CreateWidgets because of the "using" keyword.
editBoxUsername?.Dispose();
editBoxPassword?.Dispose();
// After the gui is disposed or finialized, you should no longer execute any TGUI code. All remaining C# objects
// are disposed internally when the gui is destroyed. Finalizers or Dispose calls (which will be no-ops) are still allowed though.
gui.Dispose();
}
}
}