GUI Layouts Forms

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.

When to Use It

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.

Default form rule

Add rows through layout.addRow(). This is the API that keeps label alignment, field placement, and mnemonic buddy assignment coherent.

Basic Form

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.

Klyn FormLayout login form with aligned labels, text fields, status label, and connect button
A simple login form rendered with FormLayout. Labels keep a stable column, fields fill the remaining width, and mnemonic markers are rendered as underlined buddy shortcuts.
Full-Width Rows

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.

Spacing and Labels

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.

Login Sample

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.

Next Step

Continue with Slider Widget for range input and scale-oriented controls.