Interface controls: fields, toggles and choices
A working C# gallery with name submission, choice IDs, a slider and a progress indicator.
Choose by the data
| Need | Type and event |
|---|---|
| Short displayed text | Label |
| Formatted text, selection, link metadata | RichTextLabel; handle MetaClicked for links |
| Invoke an action | Button.Pressed |
| Store yes/no | CheckButton or CheckBox, Toggled |
| Enter one line | LineEdit, TextChanged / TextSubmitted |
| Edit multiple lines | TextEdit; CodeEdit specializes in code |
| Choose one option | OptionButton.ItemSelected |
| A selectable item list | ItemList |
| Adjust a number | HSlider/VSlider or SpinBox |
| Display a noneditable value | ProgressBar / TextureProgressBar |
| Image without an action | TextureRect; TextureButton for a textured button |
| A separate dialog window | AcceptDialog/ConfirmationDialog: Window types, not Containers |
Do not imitate text input with a Label and global key polling: built-in text editors handle selection, a caret and character input. Do not blindly execute arbitrary RichTextLabel link targets; MetaClicked supplies metadata, not an obligation to act on it.
Run the gallery
Add UiSampleStyle.cs, attach WidgetGalleryDemo to a Control root, build and run with F6. Enter a name and press Enter: the status displays it. The toggle hides/shows progress. The slider changes its value; quality options have stable IDs 100/200/300. The multiline field can be edited independently.
WidgetGalleryDemo.cs
using Reckfell;
public partial class WidgetGalleryDemo : Control
{
public LineEdit NameInput { get; private set; } = null!;
public CheckButton EnabledSwitch { get; private set; } = null!;
public OptionButton Quality { get; private set; } = null!;
public HSlider Slider { get; private set; } = null!;
public ProgressBar Progress { get; private set; } = null!;
public Label Status { get; private set; } = null!;
public int SubmittedCount { get; private set; }
public override void _Ready()
{
UiSampleStyle.Prepare(this);
var margin = new MarginContainer(); AddChild(margin); margin.SetAnchorsAndOffsetsPreset(LayoutPreset.FullRect, margin: 16);
var scroll = new ScrollContainer { HorizontalScrollMode = ScrollContainer.ScrollMode.Disabled }; margin.AddChild(scroll);
var column = new VBoxContainer { SizeFlagsHorizontal = SizeFlags.ExpandFill }; scroll.AddChild(column);
column.AddChild(new Label { Text = UiSampleStyle.Text("Элементы интерфейса", "Interface controls") });
NameInput = new LineEdit { Name = "NameInput", PlaceholderText = UiSampleStyle.Text("Имя игрока", "Player name") }; column.AddChild(NameInput);
EnabledSwitch = new CheckButton { Text = UiSampleStyle.Text("Показывать прогресс", "Show progress"), ButtonPressed = true }; column.AddChild(EnabledSwitch);
Quality = new OptionButton(); column.AddChild(Quality);
Quality.AddItem(UiSampleStyle.Text("Низкое", "Low"), 100);
Quality.AddItem(UiSampleStyle.Text("Среднее", "Medium"), 200);
Quality.AddItem(UiSampleStyle.Text("Высокое", "High"), 300); Quality.Select(1);
Slider = new HSlider { MinValue = 0, MaxValue = 100, Step = 1, Value = 25 }; column.AddChild(Slider);
Progress = new ProgressBar { MinValue = 0, MaxValue = 100, Value = Slider.Value, ShowPercentage = true }; column.AddChild(Progress);
column.AddChild(new TextEdit { Text = UiSampleStyle.Text("Многострочный текст", "Multiple lines of text"), CustomMinimumSize = new Vector2(0, 90) });
Status = new Label { Text = UiSampleStyle.Text("Готово", "Ready"), AutowrapMode = TextServer.AutowrapMode.WordSmart }; column.AddChild(Status);
Slider.ValueChanged += value => Progress.Value = value;
EnabledSwitch.Toggled += enabled => Progress.Visible = enabled;
Quality.ItemSelected += index => Status.Text = "Quality ID: " + Quality.GetSelectedId();
NameInput.TextSubmitted += text => { SubmittedCount++; Status.Text = UiSampleStyle.Text("Имя: ", "Name: ") + text; };
}
}Value, index and event
OptionButton.Selected is an index in the current list; GetSelectedId() is an option ID. A stable ID is more useful for saving a choice than a row number that changes after reordering. If you omit IDs, do not expect your external identifier scheme to appear automatically.
Assign unique stable IDs in your save schema. OptionButton.Select(index) changes selection programmatically without emitting ItemSelected: refresh the model/label explicitly after restoring settings. For CheckButton/CheckBox, SetPressedNoSignal restores state without Toggled; update linked elements separately too. No signal does not mean no value change.
Range controls use MinValue, MaxValue and Step. ScrollBar also has Page, which affects its permitted upper bound; do not transplant that meaning into a ProgressBar percentage. Use SetValueNoSignal for initial slider loading when it must not invoke business logic. Explicitly refresh a linked indicator afterward: its ValueChanged handler did not run.
Text received from UI is not validated game data. Apply your own length and name rules; the gallery demonstrates event wiring, not an account policy. Programmatic assignment, user input and line submission are different operations with different signals.
Enable wrapping where variable-length text needs it and check translations. The gallery uses ScrollContainer so long content scrolls instead of requiring the whole window to expand.