Vega — Layout in der Praxis

Vega kennt keinen Layoutmanager mit Zwängen und Gewichten. Es gibt zwei Mittel, und beide sind einfach genug, um sie im Kopf zu behalten: Align verteilt Fläche, Anchors verteilt Zuwachs. Alles Weitere ergibt sich aus der Reihenfolge, in der Kinder angelegt werden.

Vega-Guides · Eigenschaften · Anwendungen aufbauen


Die Reihenfolge ist das Layout

ApplyLayout geht die Kinder der Reihe nach durch. Jedes ausgerichtete Kind schneidet sich seinen Streifen vom verbleibenden Rest ab; was übrig bleibt, bekommt das AL_CLIENT-Kind.

+--------------------------------+
|  kopf        AL_TOP            |
+--------+-+---------------------+
| links  |t|  mitte              |
| AL_LEFT|e|  AL_CLIENT          |
|        |i|                     |
|        |l|                     |
+--------+-+---------------------+
|  fuss        AL_BOTTOM         |
+--------------------------------+

Daraus folgen drei Regeln:

  • Ränder zuerst, AL_CLIENT zuletzt. Wer den Editor als erstes Kind anlegt, gibt ihm die ganze Fläche — die Leisten danach bekommen nichts mehr.
  • Zwei AL_CLIENT-Kinder sind einer zu viel. Das zweite bekommt, was das erste übrig lässt: nichts.
  • Ein Streifen braucht seine Dicke. Bei AL_TOP/AL_BOTTOM zählt Height, bei AL_LEFT/AL_RIGHT zählt Width; die jeweils andere Angabe wird überschrieben.

ApplyLayout wirkt eine Ebene tief

ApplyLayout setzt Left/Top/Width/Height der eigenen Kinder direkt — nicht über SetBounds. Ein Container erfährt davon also nichts und richtet seine eigenen Kinder nicht aus. Wer verschachtelt, zieht das im OnResize des Fensters nach:

fn OnResize(sender: TControl): void {
    if (g_mitte != null) { g_mitte.ApplyLayout(); }
    g_form.Invalidate();
}

Und einmal von Hand nach ShowForm, damit schon das erste Bild stimmt.


Anker

Anchors entscheidet, was beim Vergrößern mitwandert. Es ist eine Bitmaske:

Konstante Wert Wirkung
ANCHOR_LEFT 1 Abstand zum linken Rand bleibt
ANCHOR_TOP 2 Abstand nach oben bleibt
ANCHOR_RIGHT 4 Abstand zum rechten Rand bleibt
ANCHOR_BOTTOM 8 Abstand nach unten bleibt

Vorgabe ist ANCHOR_LEFT | ANCHOR_TOP — das Element klebt oben links. Zwei gegenüberliegende Anker bedeuten mitwachsen: ANCHOR_LEFT | ANCHOR_RIGHT zieht die Breite mit dem Fenster.

Anker und Align schließen sich aus: Ein ausgerichtetes Kind bekommt seine Geometrie ohnehin vom Layout.


Splitter und ScrollBox

  • NewSplitter(AL_LEFT) legt einen Ziehbalken an, der die davor angelegte Spalte greifbar macht. MinSize verhindert, dass sie ganz zugezogen wird. Der Splitter selbst ist ein ausgerichtetes Kind und gehört unmittelbar hinter das, was er greifen soll.
  • NewScrollBox() mit AutoScroll := true zeigt Bildlaufleisten, sobald der Inhalt größer ist als die Fläche. Kinder darin behalten ihre Koordinaten; gescrollt wird der Ausschnitt.

Vollständiges Beispiel

Kopfzeile, Fußzeile mit rechts geankertem Knopf, linke Spalte mit Splitter, verschachtelter Container mit ScrollBox:

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.Layout;
import Vega.Backend;
import Vega.BackendAuto;
import Vega.Forms;

var g_app: TApplication;
var g_form: TForm;
var g_mitte: TPanel;

fn OnBeenden(sender: TControl): void { g_app.Terminate(); }

// ApplyLayout wirkt nur eine Ebene tief: die Kinder des Fensters werden
// ausgerichtet, deren eigene Kinder nicht. Verschachtelte Container ziehen
// ihr Layout deshalb hier nach.
fn OnResize(sender: TControl): void {
  if (g_mitte != null) { g_mitte.ApplyLayout(); }
  g_form.Invalidate();
}

fn main(): int64 {
  g_app := new TApplication(NewPlatformBackend());
  if (!g_app.Ready) { PrintLn("Kein Fenstersystem erreichbar."); return 1; }

  g_form := new TForm(560, 360, "Layout");
  g_form.OnResize := OnResize;

  // 1. Kopfzeile
  var kopf: TPanel := new TPanel();
  kopf.Height := 32;
  kopf.Align := AL_TOP;
  kopf.SetParent(g_form);

  // 2. Fusszeile mit einem Knopf, der rechts unten klebt
  var fuss: TPanel := new TPanel();
  fuss.Height := 40;
  fuss.Align := AL_BOTTOM;
  fuss.SetParent(g_form);

  var ende: TButton := new TButton("Beenden");
  ende.SetBounds(430, 6, 120, 28);
  ende.Anchors := ANCHOR_RIGHT | ANCHOR_BOTTOM;
  ende.OnClick := OnBeenden;
  ende.SetParent(fuss);

  // 3. Linke Spalte, danach der Splitter, der sie greifbar macht
  var links: TPanel := new TPanel();
  links.Width := 160;
  links.Align := AL_LEFT;
  links.SetParent(g_form);

  var teiler: TSplitter := NewSplitter(AL_LEFT);
  teiler.MinSize := 80;
  teiler.SetParent(g_form);

  // 4. Rest: ein Container, der seine eigenen Kinder ausrichtet
  g_mitte := new TPanel();
  g_mitte.Align := AL_CLIENT;
  g_mitte.SetParent(g_form);

  var oben: TLabel := new TLabel("obere Haelfte");
  oben.Height := 24;
  oben.Align := AL_TOP;
  oben.SetParent(g_mitte);

  var rest: TScrollBox := NewScrollBox();
  rest.Align := AL_CLIENT;
  rest.AutoScroll := true;
  rest.SetParent(g_mitte);

  // Inhalt, der breiter ist als die Flaeche — dafuer die ScrollBox
  var breit: TLabel := new TLabel("ein sehr breiter Inhalt, der scrollen muss");
  breit.SetBounds(8, 8, 900, 20);
  breit.SetParent(rest);

  if (!g_app.ShowForm(g_form)) { return 2; }
  g_form.ApplyLayout();
  OnResize(g_form);
  g_app.Run();
  g_app.Shutdown();
  return 0;
}

Übersetzen: lyxc layout.lyx -I . -I platform/linux -o layout aus der Wurzel von lyx-vcl. Nachgemessen mit lyxc 1.1.3I, übersetzt fehlerfrei.


Wenn das Layout nicht stimmt

Symptom Ursache
Ein Streifen ist unsichtbar Er wurde nach dem AL_CLIENT-Kind angelegt
Der Streifen hat die falsche Dicke Bei AL_TOP/AL_BOTTOM zählt Height, nicht Width (und umgekehrt)
Kinder eines Containers liegen übereinander Sein ApplyLayout wird nie gerufen
Beim ersten Bild sitzt alles falsch, nach dem ersten Ziehen richtig ApplyLayout nach ShowForm fehlt
Ein Knopf wandert beim Vergrößern nicht mit Anchors steht auf der Vorgabe (links/oben)

Letzte Aktualisierung: 2026-08-19 — Beispiel mit lyxc 1.1.3I übersetzt; Splitter/ScrollBox gegen Vega/Layout.lyx abgeglichen.