====== Vega: Anwendungen aufbauen ======
Die Seite beschreibt die Muster, nach denen eine größere Vega-Anwendung entsteht — Layout, eigene Steuerelemente, Zeitgeber, Dialoge. Sie ergänzt [[lyx_-_programmiersprache:vega:controls|Steuerelemente]] (was es gibt) um die Frage, wie man es zusammensetzt.
→ [[lyx_-_programmiersprache:vega|Vega VCL]] · [[lyx_-_programmiersprache:vega:architektur|Architektur]] · [[lyx_-_programmiersprache:vega:lyx-eigenheiten|Lyx-Eigenheiten]]
----
===== Die sechs Regeln =====
- **Die Reihenfolge der Kinder ist das Layout.** ''ApplyLayout'' arbeitet die Kinder der Reihe nach ab; jedes ausgerichtete Kind nimmt sich seinen Rand vom Rest. Alle Ränder (''AL_TOP'', ''AL_BOTTOM'', ''AL_LEFT'') müssen deshalb **vor** dem ''AL_CLIENT''-Kind angelegt werden — sonst bekommt der Rand nichts mehr ab.
- **''ApplyLayout'' wirkt nur eine Ebene tief.** Es setzt ''Left''/''Top''/''Width''/''Height'' der Kinder direkt, nicht über ''SetBounds'' — ein verschachtelter Container erfährt davon nichts. Wer Container in Containern hat, ruft deren ''ApplyLayout'' im ''OnResize'' des Fensters selbst nach.
- **Einmal von Hand ausrichten.** Nach ''ShowForm'' folgt ein ''ApplyLayout'', damit schon das erste Bild stimmt und nicht erst das nach der ersten Größenänderung.
- **Modulvariablen stehen alle oben.** Bis lyxc 1.1.3D zerfiel eine Modulvariable, die vor ihrer Deklaration benutzt wurde, still in zwei ([[https://github.com/SEOLizer/LyX-Compiler/issues/1665|#1665]]). Die Gewohnheit bleibt sinnvoll: sie macht den Zustand eines Fensters an einer Stelle sichtbar.
- **Das Backend kommt aus dem Include-Pfad, nicht aus einer Fallunterscheidung.** ''Vega.BackendAuto'' liegt je einmal unter ''platform/linux'' und ''platform/win64''; ''extern''-Deklarationen binden hart, auch ungenutzt. Deshalb entscheidet der Übersetzungsaufruf, nicht der Quelltext.
- **Der Fokus wird gesetzt, nicht geerbt.** Ohne ''Dispatcher.SetFocus'' laufen Tastendrücke ins Leere, bis jemand hineinklickt.
----
===== Gerüst =====
Das folgende Programm zeigt alle Bausteine auf engstem Raum: eigenes Steuerelement mit ''Paint'', Randleiste plus ''AL_CLIENT'', Knopf mit Handler und ein Zeitgeber, der die Anzeige fortschreibt.
unit Main;
import std.io;
import Vega.Types;
import Vega.Events;
import Vega.Canvas;
import Vega.Theme;
import Vega.Control;
import Vega.Font;
import Vega.Strings;
import Vega.Lists;
import Vega.Style;
import Vega.StdCtrls;
import Vega.Backend;
import Vega.BackendAuto;
import Vega.Forms;
// Modulvariablen stehen ALLE oben — eine Variable, die erst nach ihrer
// ersten Verwendung deklariert wird, zerfiel bis lyxc 1.1.3D still in zwei.
var g_app: TApplication;
var g_form: TForm;
var g_anzeige: TAnzeige;
var g_zaehler: int64;
var g_timer: TTimer;
// Eigenes Steuerelement: von TControl ableiten und Paint ueberschreiben.
pub type TAnzeige = class extends TControl {
Wert: int64;
fn Create(): void {
self.Init();
self.Wert := 0;
self.Height := 40;
}
override fn Paint(canvas: TCanvas): void {
var r: TRect := self.ClientRect();
canvas.FillRect(r, RGB(240, 240, 240));
var f: TFont := DefaultFont();
f.DrawText(canvas, 8, 10, IntToStr(self.Wert), RGB(0, 0, 0));
}
}
fn OnTick(sender: TTimer): void {
g_zaehler := g_zaehler + 1;
g_anzeige.Wert := g_zaehler;
g_anzeige.Invalidate();
}
fn OnEnde(sender: TControl): void {
g_app.Terminate();
}
fn main(): int64 {
g_app := new TApplication(NewPlatformBackend());
if (!g_app.Ready) { PrintLn("Kein Fenstersystem erreichbar."); return 1; }
g_form := NewForm(320, 200, "Praxis");
// Reihenfolge IST das Layout: Raender zuerst, AL_CLIENT zuletzt.
var leiste: TControl := new TControl();
leiste.Height := 32;
leiste.Align := AL_BOTTOM;
g_form.AddChild(leiste);
var b: TButton := new TButton("Schliessen");
b.SetBounds(8, 4, 120, 24);
b.OnClick := OnEnde;
leiste.AddChild(b);
g_anzeige := new TAnzeige();
g_anzeige.Align := AL_CLIENT;
g_form.AddChild(g_anzeige);
if (!g_app.ShowForm(g_form)) { return 2; }
g_form.ApplyLayout();
g_timer := NewTimer(500);
g_timer.OnTimer := OnTick;
g_timer.Start();
g_app.AddTimer(g_timer);
g_app.Run();
g_app.Shutdown();
return 0;
}
Übersetzen aus der Wurzel des ''lyx-vcl''-Repositorys:
lyxc praxis.lyx -I . -I platform/linux -o praxis
Nachgemessen mit ''lyxc 1.1.3I'': übersetzt fehlerfrei, rund 770 KB.
----
===== Eigene Steuerelemente =====
Ein eigenes Element leitet von [[lyx_-_programmiersprache:vega:controls:tcontrol|TControl]] ab, ruft im Konstruktor ''self.Init()'' und überschreibt ''Paint'':
* ''self.ClientRect()'' liefert die Fläche **ohne** Rahmen.
* Gezeichnet wird über ''TCanvas'' (''FillRect'') und ''TFont'' (''DrawText'', ''TextWidth'', ''TextHeight'').
* ''self.Hovered'' und ''self.Pressed'' stehen für Zustandsdarstellung bereit.
* ''self.CanFocus'' entscheidet, ob das Element Tastatureingaben bekommt.
* Nach einer Zustandsänderung ''Invalidate()'' rufen — Vega zeichnet nicht von selbst neu.
Für Elemente, deren Inhalt an Zeichenpositionen ausgerichtet sein soll (Tabellen, Editoren), ist eine **selbst gezeichnete Fläche** der ruhigere Weg als ein Container voller Labels: Pixelabstände wandern bei jeder Textänderung, Zeichenpositionen nicht.
----
===== Zeitgeber =====
g_timer := NewTimer(20); // Millisekunden
g_timer.OnTimer := OnTick;
g_timer.Start();
g_app.AddTimer(g_timer); // ohne AddTimer feuert er nie
Ein Zeitgeber läuft durch; ob sein Handler etwas tut, entscheidet der Handler. Das ist einfacher zu überblicken als ein Timer, der ständig an- und abgemeldet wird.
----
===== Dialoge =====
''ShowModal'' braucht die Anwendung. Wer Dialoge in einer eigenen Unit hält, muss ihr die [[lyx_-_programmiersprache:vega:controls:tapplication|TApplication]] bekannt machen — sonst steigt jede Dialogaktion **still** wieder aus:
g_app := app; // vor dem ersten Dialogaufruf
----
===== Menüs =====
Die Menüleiste liegt als Kind auf ''0/0'' und nimmt am Layout **nicht** teil. Zwei Folgen:
* Ein Platzhalter in Höhe von ''f.MenuHeight()'' als erstes Kind verhindert, dass sich die erste Zeile darunterlegt.
* ''SetMenu'' setzt die Breite einmalig aus der damaligen Fensterbreite; im ''OnResize'' gehört ''f.Menu.Width := f.Width'' nachgezogen.
Letzte Aktualisierung: 2026-08-19 — Seite neu geschrieben; Muster aus einer bestehenden Vega-Anwendung abgeleitet, Beispielprogramm mit ''lyxc 1.1.3I'' übersetzt.