PyHML Language Reference

PyHML (PyHMI Markup Language) is a declarative UI description format inspired by Qt QML. It uses a YAML-compatible, indented syntax to describe UI hierarchies. PyHML files are parsed at runtime, constructing a widget tree that the engine renders on the active display backend.

Basic Syntax

PyHML uses indentation to define parent-child relationships. Each line declares a widget or component, followed by its properties:

Window:
  width: 320
  height: 240
  title: "My App"

  Label:
    text: "Hello, World!"
    color: "#333333"
    fontSize: 16

The Window is the root element. Label is a child of Window, indicated by indentation. Properties are assigned with key: value syntax.

Component Hierarchy

Nesting is defined by indentation. Each level of indentation creates a parent-child relationship:

Window:
  layout: Column
  padding: 10

  Label:
    text: "Username"

  TextField:
    id: username

  CheckBox:
    text: "Remember me"

  Button:
    text: "Login"
    onClicked: login()

In this example, Label, TextField, CheckBox, and Button are all children of Window. The Column layout arranges them vertically.

Property Assignment

Properties are assigned using YAML-style syntax. Supported types:

Type Syntax Example
String Quoted or unquoted text: "Hello"
Integer Plain number width: 320
Float Decimal number opacity: 0.5
Boolean true / false visible: true
Color Hex string color: "#FF5733"
List Inline or block values: [1, 2, 3]
Object Nested mapping font: {name: "Arial", size: 14}

IDs and References

Widgets can be assigned an id for cross-component referencing:

Slider:
  id: volume
  min: 0
  max: 100
  value: 50

Label:
  text: "Volume: {{ volume.value }}"

The id creates a reference that can be used in data bindings, signal handlers, and Python code.

Data Binding

PyHML supports one-way and two-way data binding using {{ }} expression syntax:


Label:
  text: "{{ temperature.value }} °C"


TextField:
  text: "{{= user.name }}"


Label:
  text: "{{ battery.percent > 20 ? 'OK' : 'Low' }}"

One-way binding ({{ }}) updates the target when the source changes. Two-way binding ({{= }}) syncs changes in both directions.

Signal Handlers

Signal handlers use the on<SignalName> prefix. They accept Python expressions or function calls:

Button:
  text: "Submit"
  onClicked: submit_form()

Slider:
  id: brightness
  onValueChanged: set_light(value)

TextField:
  id: search
  onTextChanged: filter_results(text)

Available signals depend on the widget. Common signals: Clicked, ValueChanged, TextChanged, Pressed, Released, FocusIn, FocusOut.

Layouts

PyHMI supports two layout engines:

Flex Layout

Row and column layouts with alignment, spacing, and stretch factors.

Window:
  layout: Column
  spacing: 10
  alignment: center

  Label:
    text: "Title"

  Button:
    text: "OK"
    stretch: 1

  Button:
    text: "Cancel"
    stretch: 1

Grid Layout

Row and column grid with span, alignment, and flexible sizing.

Window:
  layout: Grid
  columns: 2
  rows: 2
  spacing: 5

  Label:
    text: "Name"

  TextField:
    id: name

  Label:
    text: "Age"

  TextField:
    id: age
    columnSpan: 2

Animations

Animations are declared inline on widgets:

Button:
  text: "Click me"
  animations:
    - property: opacity
      from: 1.0
      to: 0.5
      duration: 300
      easing: easeInOut
      trigger: pressed

Supported easing curves: linear, easeIn, easeOut, easeInOut, bounce.

Style Templates

Style templates define reusable visual properties. Applied at widget, class, or theme level:

styles:
  primaryButton:
    backgroundColor: "#4A90D9"
    textColor: "#FFFFFF"
    borderRadius: 8
    padding: 10
    fontSize: 14

Window:
  Button:
    text: "Submit"
    style: primaryButton

Custom Elements

Custom widgets defined in Python can be used in PyHML:



Window:
  MyGauge:
    value: 75
    maxValue: 100
    color: "#4A90D9"
    onValueChanged: update_label(value)

Custom elements support property binding, event handling, and style templates. They can be nested within other custom elements.

QML Import

PyHMI supports loading Qt QML files directly. The QML importer translates QML syntax to PyHMI widget trees:

from pyhmi import Application

app = Application(backend="sdl2")
app.load_qml("design.qml")
app.run()

Supported QML features: property assignment, signal handlers, data binding, layouts, and animations.

Scene Management

Scenes are self-contained PyHML files. Navigation is handled by the scene manager:

from pyhmi import Application

app = Application(backend="sdl2")
app.load_scene("login.pyhml")

# In Python code:
app.navigate("dashboard.pyhml", data={"user": username})
app.back()

Scenes support data segue for passing data between scenes during navigation.