Die Sprache

Datei

Ereignisse können auch Inline-Skripte ausführen. scriptLanguage: "lua" wählt Lua auf Dateiebene; ohne Angabe gilt JavaScript. Siehe Inline-Skripte.

Eine Datei enthält in beliebiger Zahl und Reihenfolge:

Oberste Ebene
Dialog Name { ... } ein Dialog mit eigener Größe (size), die App öffnet den Rahmen
Screen Name { ... } der Inhalt einer Seite; Geometrie und Seite kommen von der App
component Name : Basistyp { ... } ein wiederverwendbares Element
record Name { typ feld ... } ein Datentyp der App, z. B. eine Zeile einer Liste

Elemente

qml
Typ [id] {
    property: wert
    Kind { ... }
}
Typ aura-ui eigene Properties
Item Node –
Rect RectNode color, radius, corners: topLeft, topRight, bottomRight, bottomLeft, border: breite, farbe, gradient: oben, unten
Text TextNode text, font: familie, größe[, gewicht], weight, color, align: left|center|right[, top|center|bottom], wrap: breite[, ausrichtung], fit: true|mindestgröße, lineHeight (QML-Faktor), letterSpacing (px), pixelSize/minimumPixelSize (px, ohne Context::fontSize), underline
Image ImageNode source: "name.png" (Context::image) oder image: wert (ein Bild der App, Typ image), fill: stretch|crop|fit|pad, radius, corners
Svg SvgNode source: "name.svg", fill: farbe
Scroll ScrollNode contentHeight, contentY; mit direction: horizontal waagerecht: contentWidth, contentX. Steckt ein waagerechter in einem senkrechten, entscheidet die Richtung des Fingers
QrCode QrCodeNode text (Inhalt), color
Html HtmlNode text (HTML wie QML RichText), font: familie, größe, color, lineHeight, margin (documentMargin); ohne height so hoch wie der Text bei seiner Breite
Column ColumnNode spacing, padding, align: left|center|right, justify; stapelt die sichtbaren Kinder von oben und wird so hoch wie sie (siehe Layouts)
Row RowNode spacing, padding, align: top|center|bottom, justify, wrap: true, direction: leftToRight|rightToLeft; reiht die sichtbaren Kinder von links auf und wird so breit wie sie, bzw. von seinem rechten Rand aus
Grid GridNode columns, spacing, padding, cell: breite, höhe; Zellen in der Größe des ersten sichtbaren Kindes (oder cell), wird so hoch wie die Zeilen
Popover PopoverNode color, markerPos, unfold (gezeigter Teil der Höhe, 0–1; enter: unfold 0 300 linear klappt es auf); Sprechblase mit Marker oben
Ripple RippleNode color (grau), opacity (0,4), size (200 × 200); Rückmeldung seines Elternelements: sitzt beim Drücken am Finger und pulsiert (1 ↔ 1,1, je 500 ms), wächst nach dem Tippen in 500 ms auf das Vierfache, erst dann läuft das onTap des Elternelements (ohne Animator sofort). Als letztes Kind, damit es oben liegt; das Elternelement schneidet seine Kinder ab (clip)
TextField TextFieldNode (aura/ui/text_input.h) text (Startwert, siehe Texteingabe), font, weight, color, align, letterSpacing, pixelSize, placeholder, placeholderColor (#cccccc), masked (* je Zeichen), maxLength (Zeichen), characters (die erlaubten Zeichen, z. B. "0123456789*#"), focus: true, onChange: signal, onAccept: signal; eine Zeile mit Schreibmarke, schneidet ab und rollt mit der Schreibmarke
Keyboard KeyboardNode (aura/ui/text_input.h) layout: "DE" (CZ, DE, DK, EN, FI, FR, NL, NO, PL, SE, SI, SK, auch klein; "alphanum": 800 × 240, Ziffern und Großbuchstaben, Backspace, OK, Abbrechen), color, radius, border, keyColor, textColor, accentColor (Umschalttasten), okColor, cancelColor, cancelText, okKey: false, onOk: signal, onCancel: signal; Bildschirmtastatur, 960 × 300, auf die eigene Größe skaliert
Button ButtonNode (aura/ui/controls.h) text, font, weight, textColor (weiß), color (#404040), pressedColor (sonst color dunkler), radius (8), border; Taste mit Text in der Mitte, Standardgröße 200 × 60 (siehe Bausteine)
CheckBox CheckBoxNode text, font, textColor, color (Kästchen), radius, checked, onToggle: signal; ein Tipp schaltet um
Switch SwitchNode wie CheckBox, dazu trackColor (aus); Schiebeschalter, color (an)
RadioButton RadioButtonNode wie CheckBox, dazu group; ein Tipp wählt ihn und nimmt die Wahl der anderen derselben Gruppe weg (ohne group: seiner Geschwister). onToggle meldet nur der neu gewählte
ComboBox ComboBoxNode options (Liste von Texten), index (-1: keiner), placeholder, font, textColor, color, radius, border, listColor, listTextColor, selectedColor, visibleRows (6), onSelect: signal; Auswahlliste: ein Tipp öffnet die Liste darunter über der ganzen Szene (oder darüber, wenn unten kein Platz ist), ein Tipp daneben schließt sie
Slider SliderNode value, from (0), to (1), step, color, trackColor, onChange: signal; Ziehen oder Tippen auf die Bahn
ProgressBar ProgressBarNode value, from (0), to (1), color, trackColor, radius (halbe Höhe)
Rive RiveNode source: "goodbye.riv" (Context::file); spielt die Standard-State-Machine des Standard-Artboards (sonst seine erste Animation) endlos über den Animator, eingepasst wie PreserveAspectFit
WebView aura::webview::WebViewNode (libaura-webview) url, script (JavaScript, läuft in jeder Seite vor deren eigenen Skripten); Chromium über CEF, bedienbar per Touch, WebChannel zu C++ (aura.call, aura.on). Nur in Programmen mit AURA_WITH_WEBVIEW, siehe aura-webview.md

Elementtypen der App: Was eine App selbst zeichnet, beschreibt eine aura-elements.json neben oder über den .aura-Dateien, die es benutzen:

Das folgende Beispiel beschreibt einen von der Anwendung bereitgestellten BadgeNode, keinen eingebauten AURA-Elementtyp.

json
{
	"Badge": {
		"type": "BadgeNode",
		"header": "widgets/badge_node.h",
		"properties": {
			"color": {"type": "color"},
			"label": {"type": "string", "set": "setLabel()"}
		}
	}
}

Alle Elemente haben außerdem:

Property Bedeutung
name objectName (Fernsteuerung, Logs); ohne name gilt die ID
x, y, width, height, size: w, h Geometrie
place: ... Anker, siehe unten
visible, opacity, rotation, scale, clip, glow wie in aura-ui (clip schneidet rechteckig, wie Qt Quick; glow leuchtet weiß, z. B. glow: root.pressed)
onTap: signal, onTap: signal(args), onTap: ignore löst ein Signal aus bzw. schluckt den Tap
enabled: false keine Eingaben für das Element und seine Kinder (QML enabled); Bausteine blenden sich dabei ab
grow: gewicht in einem Column/Row: ein Anteil am freien Platz in Richtung des Layouts (QML Layout.fillHeight/fillWidth)
stretch: true in einem Column/Row: füllt quer zur Richtung (Breite bzw. Höhe), im Grid die Zelle
minWidth, maxWidth, minHeight, maxHeight Grenzen für grow und stretch (0: keine)
onSettled: signal eine Animation des Elements (animate:) ist angekommen, siehe Animationen
pressSink: versatz, ms sinkt beim Drücken ein
spin: ms dreht sich endlos im Uhrzeigersinn, eine Umdrehung in ms
loop: eigenschaft von bis ms [easing] [pause ms], … pendelt endlos zwischen zwei Werten, siehe Animationen

Text im Detail:

Anker (place)

place: left 44, below title 30, centerY -20 wird zu aura::ui::place(node).left(44).below(*title, 30).centerY(-20) (siehe graphics.md). Die Reihenfolge zählt.

Direktive Bedeutung
left, right, top, bottom [Abstand] zum Rand des Parents
centerX, centerY [Versatz], center im Parent zentriert, gerundet
below, above, rightOf, leftOf Element [Abstand] neben einem Element
alignLeft, alignTop, alignBottom Element [Versatz] an einem Element ausgerichtet
centerXOn, centerYOn Element auf die Mitte eines Elements

Als Element zählen IDs, die im Quelltext vorher stehen (Geschwister oder Vorfahren), parent und bei wiederholten Elementen id[index], z. B. centerYOn field[0].

Layouts: Column, Row, Grid

Sie ordnen ihre sichtbaren Kinder an, sobald ein Kind hinzukommt. Ändert sich später ein Kind (über eine Bindung oder einen Neuaufbau), ordnen sie neu an. Ihre eigene Größe folgt dem Inhalt (Column: Höhe, Row von links: Breite, Grid: Höhe), sodass andere Elemente sich darauf beziehen können:

qml
Scroll list {
    size: parent.width - 4, min(len(lines), 5) * 76
    contentHeight: productRows.height   // nach dem Bau der Zeilen
    Column productRows {
        width: parent.width
        repeat line, i in lines { CartRow { index: i; line: line } }
    }
}
// Header: rechtsbündig
Row buttons { direction: rightToLeft; spacing: 16; size: parent.width, 60 }
// Grid layout
Grid cells { columns: columns; spacing: 10 }

Unsichtbare Kinder belegen keinen Platz. Die Kinder setzen ihre Größe selbst, die Lage in Richtung des Layouts (Column: y, Row: x, Grid: beides) vergibt das Layout.

Flexibel: Mit diesen Properties verteilt ein Layout Platz, statt nur zu stapeln:

qml
Column {
    size: 400, parent.height
    padding: 20                     // 1 Wert, 2 (oben/unten, links/rechts) oder 4 (oben, rechts, unten, links)
    spacing: 10
    align: center                   // quer: left, center, right (Row: top, center, bottom)

    Text { text: tr("Title", "Titel") }
    Scroll { grow: 1 }              // nimmt die restliche Höhe
    Row {
        stretch: true               // so breit wie die Column (ohne padding)
        height: 60
        justify: spaceBetween       // start, center, end, spaceBetween, spaceAround, spaceEvenly
        DialogButton { text: "Zurück" }
        DialogButton { text: "Weiter"; grow: 1; maxWidth: 300 }
    }
}
Row tags { width: 500; wrap: true; spacing: 8 }    // bricht in Zeilen um (QML Flow), wird so hoch wie sie

Ausdrücke

Werte Zahlen (intern double, wie in QML), "Text" (mit \n, \t, \b), Farben #rrggbb/#aarrggbb, true/false, Listen [a, b]
Operatoren + - * / %, == != < > <= >=, && || !, a ? b : c; + verbindet auch Texte
Namen IDs (vorher definiert), parent, eigene Geometrie (x, y, width, height, implicitWidth, implicitHeight), Schleifenvariablen, propertys des Dialogs bzw. der Komponente (auch als root.<name>)
Element-Werte id.x, .y, .width, .height, .opacity, .rotation, .scale, .pressed, .implicitWidth/.implicitHeight (Text; Image: Bildgröße; Html: Höhe), .contentHeight (Scroll)
Datensätze zeile.feld, liste[i].feld, root.zeile.feld
Listen liste[i], len(liste), z. B. ["", "ABC", "DEF"][i]
Kontext theme.<name>, screen.width, screen.height, props.bool("ID"), props.int("ID"), props.string("ID")
Funktionen tr("id", "Deutsch"), str(zahl), replace(text, alt, neu), lower(text), upper(text), len(liste|text), fontSize(px) (Context::fontSize), ceil, floor, round, abs, min, max, range(n)

Typen werden geprüft: Ein Text, wo eine Zahl stehen muss, oder ein Feld, das der Datensatz nicht hat, bricht den Build ab.

Wiederholung und Bedingung

qml
repeat key, index in ["1", "2", "\b"] {
    Item keyItem { x: index % 3 * 94; onTap: keyPressed(key) }
}
repeat i in range(6) { Rect field { x: digitsX + i * 54 } }
repeat line, i in lines { CartRow row { line: line } }

if key == "\b" { Svg { ... } } else { Text { ... } }

Reihenfolge der Properties

Pro Element gilt diese Reihenfolge, genau wie im früheren handgeschriebenen Code:

  1. Inhalt (Text, Farben, Schrift, …),
  2. die natürliche Größe von Texten,
  3. die Geometrie (x, y, width, height, size, place, contentHeight) in Quelltext-Reihenfolge.

Deshalb funktioniert height: back.y - 30 - y nach place: left 44, below editBox 30.

Bezug auf eigene Kinder: Eine Property, die eine ID aus dem eigenen Teilbaum nennt, wird erst angewandt, wenn dieses Kind gebaut ist, und zwar direkt danach. Spätere Kinder sehen den Wert schon:

qml
component PriceRow : Rect {
    height: topicText.height + 12       // nach topicText
    Text topicText { wrap: 290 }
    Text { place: right 15, centerY }   // sieht die Zeilenhöhe
}

Gedrückt-Zustand

Nennt eine Property id.pressed, wird sie neu ausgewertet, sobald sich der Zustand ändert. Mit ihr laufen alle Nachfahren von id erneut durch, damit Anker mitwandern:

qml
Item keyItem {
    onTap: keyPressed(key)
    Rect face {
        x: keyItem.pressed ? 5 : 0
        width: parent.width - (keyItem.pressed ? 8 : 0)
        Text { size: parent.width, parent.height }   // folgt dem Rect
    }
}

id selbst wird dabei nicht neu angeordnet, sonst würde etwa ein pressSink zurückgesetzt. In Komponenten geht auch root.pressed (Taste, Footer-Button).

Texteingabe

qml
TextField code {
    font: theme.textFont, 48
    placeholder: tr("Voucher_Code", "Gutscheincode")
    maxLength: 20
    focus: true
    size: 400, 60
    onChange: codeChanged           // signal codeChanged(string text)
    onAccept: redeem                // Enter
}
Rect ok { onTap: redeem(code.text) }
Keyboard {
    layout: props.string("CurrentLanguage")          // "de", "EN", ...; unbekannt: DE
    place: centerX, bottom 20
    onOk: redeem(code.text)
    onCancel: close
}

Bausteine

qml
Column {
    padding: 24
    spacing: 16
    CheckBox agb { text: tr("Agb", "AGB gelesen"); checked: accepted; onToggle: accept }    // signal accept(bool on)
    Slider { from: 0; to: 100; step: 5; value: volume; onChange: setVolume }                // signal setVolume(real v)
    ProgressBar { value: uploaded; to: total; stretch: true }
    Button { text: tr("Next", "Weiter"); color: theme.mainColor; enabled: agb.checked; onTap: next }
}

Dialog und Screen

qml
Dialog OrderStatusDialog {
    property strings digits             // Argument der App (Zustand)
    const real digitsX: 140          // Konstante
    signal keyPressed(string key)
    size: 860, 600
    ...
}

Property-Typen: real, int, bool, string, color, image (ein Bild der App, in C++ sk_sp<SkImage>, leer erlaubt), strings (Liste von Texten, in C++ std::vector<std::string>), ein Datensatz und Datensatz[] (Liste).

Komponenten

qml
component DialogButton : Rect {
    property string text        // Argument der Instanz (": wert": Standard)
    color: theme.mainColor
    radius: 4
    pressSink: 4, 250
    Text {
        text: root.text
        fit: true
        align: center, center
        size: parent.width, parent.height
    }
}

component LanguageButton : Rect {
    property string language
    signal select                       // eigenes Signal der Komponente
    onTap: select
    ...
}
Dokumentationsquelle: docs/aura.md · Markdown herunterladen

Suche nach Themen, Widgets oder APIs.