====== 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.