FormLayout
FormLayout is the layout manager for label/field forms. It keeps labels aligned,
gives fields the remaining width, supports full-width rows, and automatically connects label
mnemonics to their input widgets.
Use FormLayout for login screens, settings dialogs, database filters, and every UI
where rows naturally read as label -> editor. It avoids manual two-column grids and
keeps the form readable when label text changes.
Add rows through layout.addRow(). This is the API that keeps label alignment,
field placement, and mnemonic buddy assignment coherent.
The most compact form declaration uses a text label and a field widget. The ampersand declares
the mnemonic: &Login: renders as Login:, underlines the L,
and lets the user press Alt+L to focus the associated field.
import klyn.gui.windows
import klyn.gui.windows.layouts
formLayout = FormLayout(rowSpacing=12, columnSpacing=14, labelWidth=96)
form = Container(formLayout)
loginField = TextBox()
loginField.placeholder = "login"
formLayout.addRow("&Login:", loginField)
passwordField = TextBox()
passwordField.placeholder = "password"
passwordField.echoMode = TextBox.ECHO_PASSWORD
formLayout.addRow("&Password:", passwordField)
You can also pass an existing Label. In that case FormLayout still assigns
the label's buddy to the field, so the mnemonic behavior remains automatic.
FormLayout. Labels keep a stable column, fields
fill the remaining width, and mnemonic markers are rendered as underlined buddy shortcuts.
A form sometimes needs a button, separator, status label, or section title that spans both
columns. Use the single-widget overload of addRow() for that case.
status = Label("")
formLayout.addRow(status)
connectButton = Button("Connect")
connectButton.isDefaultButton = true
formLayout.addRow(connectButton)
If you need explicit per-widget hints, FormLayoutParams exposes isLabel
and fullRow. Most application code should not need it; prefer the addRow()
overloads first.
rowSpacing controls vertical spacing, columnSpacing controls the gap between
labels and fields, and labelWidth reserves a stable label column. When
labelWidth is zero, the layout computes the width from the managed labels.
layout = FormLayout(
rowSpacing=12,
columnSpacing=14,
labelWidth=96,
labelAlign="start"
)
Keep the label column explicit when the form is part of a larger window. This avoids small width changes when translations, KSS fonts, or validation text evolve.
samples/gui/LoginForm.kn combines FormLayout, password input,
default-button behavior, method-reference events, and a prepared SQL statement. It is a compact
example of a real GUI form around database validation.
formLayout as FormLayout = FormLayout(rowSpacing=12, columnSpacing=14, labelWidth=96)
form as Container = Container(formLayout)
this._loginField = TextBox()
this._loginField.placeholder = "login"
this._loginField.maxLength = 128
formLayout.addRow("&Login:", this._loginField)
this._passwordField = TextBox()
this._passwordField.placeholder = "password"
this._passwordField.echoMode = TextBox.ECHO_PASSWORD
this._passwordField.maxLength = 256
formLayout.addRow("&Password:", this._passwordField)
klyn samples/gui/LoginForm.kn
The sample requires a reachable MariaDB instance matching the SQL block documented at the top of the file. The GUI part remains useful as a layout reference even when the database is not configured locally.
Continue with Slider Widget for range input and scale-oriented controls.