Vega — Themes anwenden

Das Aussehen einer Vega-Anwendung steht nicht im Code der Steuerelemente, sondern in einem Theme. Der Guide zeigt, wie man es benutzt: eingebaute Themes umschalten, Rollen statt Farben vergeben, ein eigenes .vtheme laden. Wie das Format innen aufgebaut ist, steht in der Themes-Referenz.

Vega-Guides · Themes-Referenz · Zeichnen


Rollen statt Farben

Der wichtigste Handgriff ist eine Zeile:

b.SetRole("primary");        // nicht: b.Color := RGB(0, 87, 184)

primary ist eine Rolle, keine Farbe. Welche Farbe daraus wird, entscheidet das Theme — und zwar für jedes Element mit dieser Rolle gleichzeitig. Ein Firmentheme, das später dazukommt, ändert das Aussehen der ganzen Anwendung, ohne dass eine Zeile Code angefasst wird.

Dasselbe gilt für Klassen (SetStyleClass): class compact etwa für enge Werkzeugleisten — rein visuell, ohne Bedeutung.


Umschalten zur Laufzeit

Funktion Wirkung
InitDefaultTheme() Das eingebaute Standardtheme aktivieren
UseTheme(id) Theme über seine Kennung wählen („vega.light“, „vega.dark“, eigene)
UseThemeMode(mode) Zwischen hell und dunkel derselben Familie wechseln
CurrentThemeId() Kennung des aktiven Themes
DefaultTheme() / SetDefaultTheme(t) Das TTheme-Objekt selbst lesen oder setzen
UseThemeFont(pfad, theme) Eine TrueType-Schrift für das Theme laden

Ein Themewechsel wirkt ohne Neustart: Die Controls fragen ihre Werte beim Zeichnen ab, nicht beim Anlegen.


Beispiel

Zwei Knöpfe mit Rollen, ein dritter schaltet zwischen hell und dunkel:

unit Main;

import std.io;
import Vega.Types;
import Vega.Events;
import Vega.Canvas;
import Vega.Theme;
import Vega.Themes;
import Vega.ThemeFile;
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;

var g_app: TApplication;
var g_stand: TLabel;
var g_dunkel: bool;

fn OnUmschalten(sender: TControl): void {
  g_dunkel := !g_dunkel;
  if (g_dunkel) { UseTheme("vega.dark"); } else { UseTheme("vega.light"); }
  var id: pchar := CurrentThemeId();
  g_stand.SetCaption(id);
}

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

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

  InitDefaultTheme();

  var f: TForm := new TForm(380, 200, "Themes");

  g_stand := new TLabel("");
  g_stand.SetBounds(16, 16, 340, 18);
  var id: pchar := CurrentThemeId();
  g_stand.SetCaption(id);
  g_stand.SetParent(f);

  // Rollen statt Farben: welche Farbe "primary" ist, entscheidet das Theme
  var b1: TButton := new TButton("Speichern");
  b1.SetBounds(16, 56, 140, 30);
  b1.SetRole("primary");
  b1.SetParent(f);

  var b2: TButton := new TButton("Loeschen");
  b2.SetBounds(176, 56, 140, 30);
  b2.SetRole("danger");
  b2.SetParent(f);

  var b3: TButton := new TButton("Hell/Dunkel");
  b3.SetBounds(16, 104, 140, 30);
  b3.OnClick := OnUmschalten;
  b3.SetParent(f);

  var b4: TButton := new TButton("Beenden");
  b4.SetBounds(176, 104, 140, 30);
  b4.OnClick := OnBeenden;
  b4.SetParent(f);

  if (!g_app.ShowForm(f)) { return 2; }
  g_app.Run();
  g_app.Shutdown();
  return 0;
}

Übersetzen: lyxc themes.lyx -I . -I platform/linux -o themes. Nachgemessen mit lyxc 1.1.3I, übersetzt fehlerfrei.


Eigenes Theme aus einer Datei

var lr: TThemeLoadResult := RegisterThemeFile("themes/corporate.vtheme", false);
UseTheme("corporate.light");

  • RegisterThemeFile(pfad, strict) liest die Datei und macht das Theme unter seiner Kennung bekannt; LoadThemeFile und LoadThemeText sind die Varianten ohne Registrierung bzw. aus einer Zeichenkette.
  • Das zweite Argument ist der strenge Modus: false lädt so viel wie möglich und sammelt die Fehler, true bricht ab.
  • Der Rückgabewert nennt Zeilennummer und Grund — hineinsehen lohnt, sonst bleibt es beim alten Aussehen, ohne dass jemand etwas merkt.

Ein .vtheme erbt und überschreibt nur, was anders sein soll:

theme "corporate.light" extends "vega.light" {
  version 1
  mode light

  tokens {
    colors {
      marke:      #0057B8
      markeHover: #00468F
    }
    metrics { rund: 4 }
  }

  button {
    borderRadius: {metrics.rund}
    role primary {
      background: {colors.marke}
      foreground: #FFFFFF
      hover { background: {colors.markeHover} }
    }
  }
}

Tokens stehen einmal und werden über {colors.marke} eingesetzt — wer die Hausfarbe ändert, ändert sie überall. Der Selektor kennt fünf Achsen: Typ, Zustand, Rolle, Klasse und Teil; Einzelheiten in der Referenz.


Abstände und Größen

Vega.Themes liefert die abgestuften Werte, damit Abstände in der ganzen Anwendung gleich ausfallen: SpacingXS (4), SpacingSM (8), SpacingMD (12), SpacingLG (16), SpacingXL (24), dazu RadiusSM/MD/LG/Round, ControlHeightSM (28), ControlHeightMD (34), MinControlHeight (24), IconMD (18) und ScrollbarWidth (12).

Eigene Zahlen im Code sind der Weg, wie eine Oberfläche über die Jahre uneinheitlich wird.


Fallstricke

  • Farbe direkt gesetzt. Ein Color := RGB(…) überlebt den Themewechsel und fällt beim dunklen Theme sofort auf. Rolle nehmen.
  • Ergebnis von RegisterThemeFile ignoriert. Bei einem Tippfehler in der Datei bleibt das alte Theme aktiv — stumm.
  • Kennung verwechselt. UseTheme erwartet die Kennung aus der Datei („corporate.light“), nicht den Dateinamen.

Letzte Aktualisierung: 2026-08-19 — API gegen Vega/Theme.lyx, Vega/ThemeFile.lyx und Vega/Themes.lyx erhoben; Beispiel mit lyxc 1.1.3I übersetzt.