Windows GUI Library
The klyn.gui.windows package provides Klyn's native widget layer for desktop
applications. It is built around typed widgets, layout managers, multicast events, and KSS
themes so application code stays explicit and statically typed.
Only klyn is imported by default. GUI applications must import the widget package
and, when needed, the layout and event packages explicitly.
import klyn.gui.windows
import klyn.gui.windows.layouts
import klyn.gui.windows.events
The main classes are MainWindow, Container, Label,
TextBox, Button, ComboBox, and the layout managers in
klyn.gui.windows.layouts.
A MainWindow owns a centralWidget. Add widgets to containers and let
a layout manager compute bounds. This keeps resize behavior in one place and avoids manual
coordinate code in ordinary forms.
import klyn.gui.windows
import klyn.gui.windows.layouts
win = MainWindow("Hello")
win.size = (420, 240)
root = win.centralWidget
root.layout = VBoxLayout(spacing=12)
root.padding = [24, 24, 24, 24]
title = Label("Welcome to Klyn")
root.add(title)
field = TextBox()
field.placeholder = "Your name"
root.add(field)
button = Button("Continue")
root.add(button)
win.centerIn(null)
win.show()
win.run()
Layouts currently include VBoxLayout, HBoxLayout,
GridLayout, FormLayout, FlowLayout, and
DockLayout. For form-oriented screens, FormLayout is usually a better
starting point than absolute positioning.
GUI events are multicast. Use += to subscribe and -= to unsubscribe.
A single event can have several handlers, so a widget can notify both application logic and
instrumentation code without replacing the previous callback.
import klyn.gui.windows
import klyn.gui.windows.events
class Controller:
public onSave(event as ActionEvent) as Void:
print("save requested")
controller = Controller()
button = Button("Save")
button.clicked += controller::onSave
button.clicked += lambda(event: ActionEvent): print(event.source)
Method references use object::method. Lambdas can capture values from the
surrounding scope and should keep an explicit event parameter type when the event payload
matters.
Use Timer for periodic GUI work such as blinking indicators, clocks, previews, or
lightweight polling. Timer callbacks are dispatched by the native event loop, not by an
arbitrary worker thread.
import klyn.gui.windows
import klyn.gui.windows.events
canvas = MyCanvas()
timer = Timer(1000)
timer.timeout += lambda(event: ActionEvent): canvas.repaint()
timer.start()
Stop timers when they are no longer needed. samples/gui/ClockSample.kn uses this
pattern to repaint an analog clock once per second.
Text fields expose editing state through TextBox. Password fields use
echoMode, and buttons can be marked as the default action for Enter-driven forms.
The native backend also supports Tab and Shift+Tab focus traversal.
import klyn.gui.windows
import klyn.gui.windows.layouts
import klyn.gui.windows.events
public class LoginWindow extends MainWindow:
private login as TextBox
private password as TextBox
private status as Label
public LoginWindow():
super("Login")
this.size = (420, 260)
root = this.centralWidget
root.layout = FormLayout(rowSpacing=12, columnSpacing=16)
root.padding = [24, 24, 24, 24]
this.login = TextBox()
this.login.placeholder = "login"
root.add(Label("Login"))
root.add(this.login)
this.password = TextBox()
this.password.echoMode = TextBox.ECHO_PASSWORD
this.password.placeholder = "password"
root.add(Label("Password"))
root.add(this.password)
submit = Button("Connect")
submit.isDefaultButton = true
submit.clicked += this::connect
root.add(Label(""))
root.add(submit)
this.status = Label("")
root.add(Label(""))
root.add(this.status)
private connect(event as ActionEvent) as Void:
if this.login.text.trim() == "":
this.status.text = "Login is required"
return
this.status.text = "Connected"
win = LoginWindow()
win.centerIn(null)
win.show()
win.run()
The default widget appearance is defined with KSS, a small CSS-like styling layer. Built-in
themes live under KLYN_HOME/lib/klyn/gui/windows/themes as
light.kss and dark.kss. The default mode is system, so
Klyn chooses the light or dark theme from the operating-system appearance when it can.
import klyn.gui.windows
import klyn.gui.windows.themes
ThemeManager.setAppearanceMode(ThemeManager.MODE_DARK)
win = MainWindow("Themed")
win.appearanceMode = ThemeManager.MODE_SYSTEM
KSS currently covers the common surface properties used by the widget set: foreground color,
background color, margins, padding, font family, font size, borders, corner radius, placeholder
color, selection color, caret color, and slider track fill color. Slider thumbs use the
resolved accent-color, while the active track segment can be overridden with
track-fill-color. Prefer the built-in theme files for default widget styling;
application-specific colors should live in application code or a dedicated app theme. See GUI Themes and KSS for mode control, custom stylesheets, and the supported KSS subset.
Window.capture() renders the window client area to a BMP file through Klyn's own
painter pipeline. It is useful for documentation, visual regression checks, and tuning layouts
without relying on an external screenshot tool.
win = MainWindow("Preview")
win.size = (640, 420)
win.capture("preview.bmp")
Captures do not include operating-system window decorations. They show the same widget tree that Klyn paints inside the client area.
Open samples/gui/Calculator.kn for a larger GUI program using layouts, buttons,
focus feedback, and event handlers. Continue with GUI Themes and KSS for appearance control, FormLayout for label/field forms, Slider Widget for scale input, then Canvas and
Custom Painting when you need a widget that draws its own pixels.