Wie ein Stil ein Widget zeichnet
Die QStyle -API verfügt über drei Arten von Funktionen: Funktionen zum Zeichnen der Widgets, statische Hilfsfunktionen für häufige und komplexe Aufgaben wie die Berechnung der Position eines Schiebereglers sowie Funktionen für die Berechnungen, die Widgets während des Zeichnens benötigen, beispielsweise zur Ermittlung ihrer Größenangaben. Der Stil unterstützt zudem einige Widgets bei der Anordnung ihrer Inhalte und kann die „ QPalette “ anpassen, mit denen die Widgets gezeichnet werden.
Diese Seite beschreibt die Bausteine, mit denen eine Stil-Implementierung arbeitet. Die Widget-Stil-Referenz listet auf, welche davon jedes Widget verwendet.
Stilelemente
QStyle zeichnen grafische Elemente. Ein Element ist ein Widget oder ein Widget-Teil, wie beispielsweise die Abschrägung einer Drucktaste, ein Fensterrahmen oder eine Bildlaufleiste. Die meisten Zeichenfunktionen nehmen vier Argumente entgegen:
- Einen Enum-Wert, der angibt, welches grafische Element gezeichnet werden soll.
- Ein „ QStyleOption “, der angibt, wie und wo dieses Element gerendert werden soll.
- Ein „ QPainter “, mit dem das Element gezeichnet werden soll.
- Das „ QWidget “, auf dem die Zeichnung ausgeführt wird. Dieses Argument ist optional.
Wenn ein Widget einen Stil auffordert, ein Element zu zeichnen, stellt es dem Stil ein „ QStyleOption “ zur Verfügung – eine Klasse, die die für das Zeichnen erforderlichen Informationen enthält. Da das „ “ alles enthält, was der Stil benötigt, kann der Stil Widgets zeichnen, ohne Widget-Code einbinden zu müssen. Sie können ein Kombinationsfeld auf jedem beliebigen Zeichenobjekt zeichnen, nicht nur auf einem „ QComboBox “.
Das Widget wird als letztes Argument übergeben, falls der Stil es für Spezialeffekte benötigt, wie beispielsweise animierte Standardschaltflächen unter macOS; der Stil darf sich jedoch nicht darauf verlassen. Widgets, die selbst mehrere Elemente zeichnen, übergeben sich selbst, ebenso wie ` QStylePainter`. Code, der direkt auf einem Malgerät zeichnet, kann ` nullptr` übergeben.
Ein Widget besteht aus einer Hierarchie oder einem Baum von Stilelementen. Wenn ein Stil beispielsweise die Anweisung erhält, eine Drucktaste zu zeichnen, zeichnet er eine Beschriftung (Text und Symbol), eine Tastenabschrägung und einen Fokusrahmen. Die Schaltflächenumrandung besteht wiederum aus einem Rahmen um die Umrandung und dem Bedienfeld. Der folgende konzeptionelle Baum zeigt die Elemente der Drucktaste in der Reihenfolge ihrer Darstellung, wobei verschachtelte Elemente von dem ihnen übergeordneten Element gezeichnet werden:
- Druckknopf
- Schaltflächenumrandung
- Standard-Schaltflächenrahmen
- Schaltflächenfeld
- Beschriftung (Symbol und Text)
- Fokusrahmen
- Schaltflächenumrandung
Die Schaltflächen in der Referenz zeigen die tatsächliche Baumstruktur für QPushButton mit den Elementnamen an.
Widgets fordern den Stil nicht unbedingt dazu auf, nur ein Element zu zeichnen. Ein Widget kann mehrere Aufrufe an den Stil senden, um verschiedene Elemente zu zeichnen. Ein Beispiel hierfür ist „ QTabWidget “, das seine Registerkarten und seinen Rahmen einzeln zeichnet.
Es gibt drei Elementtypen: primitive Elemente, Steuerelemente und komplexe Steuerelemente. Diese werden durch die Enums „ PrimitiveElement “, „ ControlElement “ und „ ComplexControl “ definiert. Die Werte jedes Enums haben ein Präfix, das ihren Typ kennzeichnet: „ PE_ “ für primitive Elemente, „ CE_ “ für Steuerelemente und „ CC_ “ für komplexe Steuerelemente. Die Dokumentation der Klasse „ QStyle “ listet diese Elemente und ihre Rollen bei der Gestaltung von Widgets auf.
Primitive Elemente
Primitive Elemente sind GUI-Elemente, die häufig vorkommen und von mehreren Widgets verwendet werden. Beispiele hierfür sind Rahmen, Schaltflächenumrandungen sowie Pfeile für Drehfelder, Bildlaufleisten und Kombinationsfelder. Primitive Elemente können nicht eigenständig existieren; sie sind immer Teil einer größeren Struktur. Sie spielen keine Rolle bei der Interaktion mit dem Benutzer, sondern dienen lediglich als passive Gestaltungselemente in der Benutzeroberfläche.
Steuerelemente
Ein Steuerelement führt eine Aktion aus oder zeigt dem Benutzer Informationen an. Beispiele für Steuerelemente sind Drucktasten, Kontrollkästchen sowie Kopfzeilenbereiche in Tabellen und Baumansichten. Ein Steuerelement ist nicht immer ein vollständiges Widget wie beispielsweise eine Drucktaste; es kann sich auch um einen Widget-Bestandteil handeln, wie etwa eine Registerkarte in einer Registerleiste oder einen Schieberegler in einer Bildlaufleiste. Steuerelemente unterscheiden sich von primitiven Elementen dadurch, dass sie nicht passiv sind: Sie sind an der Interaktion mit dem Benutzer beteiligt.
Steuerelemente, die aus mehreren Elementen bestehen, verwenden häufig den Stil, um die Begrenzungsrechtecke der Elemente zu berechnen. Die Enumeration „ SubElement “ definiert die verfügbaren Unterelemente. Diese Enumeration wird ausschließlich zur Berechnung von Begrenzungsrechtecken verwendet. Unterelemente sind keine grafischen Elemente, die wie primitive, Steuer- und komplexe Elemente gezeichnet werden.
Komplexe Steuerelemente
Komplexe Steuerelemente enthalten Untersteuerelemente. Komplexe Steuerelemente verhalten sich unterschiedlich, je nachdem, wo der Benutzer sie mit der Maus bedient und welche Tastaturtasten gedrückt werden. Dies hängt davon ab, über welchem Untersteuerelement – falls vorhanden – sich der Mauszeiger befindet oder welches gedrückt wird. Beispiele für komplexe Steuerelemente sind Bildlaufleisten und Kombinationsfelder. Bei einer Bildlaufleiste können Sie den Schieberegler mit der Maus bewegen und die Schaltflächen „Nach oben“ und „Nach unten“ betätigen. Die Enumeration „ SubControl “ definiert die verfügbaren Untersteuerelemente.
Neben der Darstellung teilt der Stil den Widgets mit, welches Unterelement der Benutzer gegebenenfalls gedrückt hat. So muss ein „ QScrollBar “ beispielsweise wissen, ob der Benutzer den Schieberegler, die Schiebereglerrille oder eine der Schaltflächen gedrückt hat.
Unterelemente sind nicht dasselbe wie Steuerelemente. Man kann den Stil nicht zum Zeichnen eines Unterelements verwenden; der Stil berechnet lediglich das Begrenzungsrechteck, in dem das Unterelement gezeichnet werden soll. Es ist jedoch üblich, dass komplexe Elemente Steuerelemente und primitive Elemente verwenden, um ihre Unterelemente zu zeichnen. Die in Qt integrierten Stile tun dies häufig. Beispielsweise verwendet „ QCommonStyle “ „ PE_IndicatorCheckBox “, um das Kontrollkästchen in Gruppenfeldern zu zeichnen, das ein Unterelement von „ CC_GroupBox “ ist. Einige Unterelemente haben ein entsprechendes Steuerelement, zum Beispiel den Schieberegler der Bildlaufleiste (SC_ScrollBarSlider und CE_ScrollBarSlider).
Unterelemente, Untersteuerelemente und Pixelmaße
Die Stilelemente und die Widgets verwenden den Stil, um die Begrenzungsrechtecke von Unterelementen und Untersteuerelementen zu berechnen. Pixelmaße, bei denen es sich um stilabhängige Größen in Bildschirmpixeln handelt, werden ebenfalls für Messungen beim Zeichnen verwendet. Drei Aufzählungslisten in „ QStyle “ stellen die verfügbaren Rechtecke und Pixelmaße dar: „ SubElement “, „ SubControl “ und „ PixelMetric “. Ihre Werte beginnen mit „ SE_ “, „ SC_ “ und „ PM_ “.
Stilhinweise
Der Stil reagiert zudem auf eine Reihe von Stilhinweisen, die durch die Werte der Enumeration „ StyleHint “ dargestellt werden. Nicht alle Widgets weisen in den verschiedenen Stilen dieselbe Funktionalität und dasselbe Erscheinungsbild auf. Wenn beispielsweise die Menüpunkte eines Menüs nicht in eine einzige Spalte auf dem Bildschirm passen, unterstützen einige Stile das Scrollen, während andere mehrere Spalten zeichnen, um alle Elemente darzustellen. Widgets fragen Hinweise mit ` styleHint()` ab.
Standard-Symbole
Ein Stil verfügt in der Regel über eine Reihe von Standardsymbolen, wie z. B. Warn-, Frage- und Fehlerbilder, für Meldungsfelder, Dateidialoge und Schaltflächen in der Titelleiste. Die Enumeration ` StandardPixmap ` benennt diese, und ` standardIcon()` gibt die ` QIcon ` für einen Wert zurück. Die Widgets von Qt verwenden diese Symbole; stellen Sie sie daher bereit, wenn Sie einen Stil implementieren.
Abstände im Layout
Der Stil berechnet die Abstände zwischen Widgets in Layouts. Es gibt zwei Möglichkeiten, diese Berechnungen durchzuführen. Sie können die Abstände über ` pixelMetric()` für ` PM_LayoutHorizontalSpacing ` und ` PM_LayoutVerticalSpacing` zurückgeben, wie es ` QCommonStyle ` tut. Alternativ können Sie ` layoutSpacing()` neu implementieren, wenn Sie mehr Kontrolle benötigen. In dieser Funktion können Sie die Abstände basierend auf den Steuerelementtypen (`QSizePolicy::ControlType`) der beiden benachbarten Widgets, deren Größenrichtlinien (`QSizePolicy::Policy`) und der Stiloption für das betreffende Widget berechnen.
Stiloptionen
Die Unterklassen von ` QStyleOption ` enthalten alle Informationen, die zur Gestaltung der einzelnen Elemente erforderlich sind. Der Aufrufer der Funktion ` QStyle ` instanziiert eine Stiloption – in der Regel auf dem Stack – und füllt sie mit den entsprechenden Werten. Je nachdem, was gezeichnet wird, erwartet der Stil eine andere Stiloptionsklasse. Das Element ` PE_FrameFocusRect ` erwartet beispielsweise ein Argument vom Typ ` QStyleOptionFocusRect `. Sie können auch eigene Unterklassen erstellen, um einen benutzerdefinierten Stil zu verwenden. Aus Leistungsgründen verfügen die Stiloptionen über öffentliche Variablen.
Widgets können sich in verschiedenen Zuständen befinden, die durch die Enumeration „ State “ definiert sind. Einige der Zustandsflags haben je nach Widget unterschiedliche Bedeutungen, andere sind jedoch für alle Widgets gleich, wie beispielsweise „ State_Enabled “. „ QStyleOption::initFrom()“ legt die allgemeinen Zustände fest; die einzelnen Widgets legen den Rest fest.
Insbesondere enthalten die Stiloptionen die Farbpalette und das Begrenzungsrechteck des zu zeichnenden Widgets. Die meisten Widgets verfügen über spezielle Stiloptionen. „ QPushButton “ und „ QCheckBox “ verwenden beispielsweise „ QStyleOptionButton “, das den Text, das Symbol und die Größe des Symbols enthält. Die „Widget-Stilreferenz“ beschreibt den genauen Inhalt jeder Option.
Wenn Sie „ QStyle “-Funktionen neu implementieren, die einen „ QStyleOption “-Parameter entgegennehmen, müssen Sie die Option häufig in eine Unterklasse wie „ QStyleOptionFocusRect “ umwandeln. Verwenden Sie „ qstyleoption_cast()“, um sicherzustellen, dass der Zeigertyp korrekt ist. Wenn das Objekt nicht vom richtigen Typ ist, gibt „ qstyleoption_cast()“ „ nullptr “ zurück:
const QStyleOptionFocusRect *focusRectOption =
qstyleoption_cast<const QStyleOptionFocusRect *>(option);
if (focusRectOption) {
//...
}Allgemeine Statusflags und -mitglieder
Einige Zustände und Variablen sind für alle Widgets gleich. Widgets setzen sie mit ` QStyleOption::initFrom()` (). Nicht alle Elemente verwenden diese Funktion. Die Widgets erstellen die Stiloptionen, und für einige Elemente sind die Informationen aus ` initFrom()` nicht erforderlich.
| Status | Wird gesetzt, wenn |
|---|---|
State_Enabled | Das Widget ist nicht deaktiviert (siehe QWidget::isEnabled()). |
State_HasFocus | Das Widget hat den Fokus (siehe QWidget::hasFocus()). |
State_KeyboardFocusChange | Der Benutzer hat den Fokus mit der Tastatur gewechselt (siehe WA_KeyboardFocusChange). |
State_MouseOver | Der Mauszeiger befindet sich über dem Widget. |
State_Active | Das Widget ist ein untergeordnetes Element des aktiven Fensters. |
Die weiteren gängigen Mitglieder sind:
| Element | Beschreibung |
|---|---|
| rect | Das Begrenzungsrechteck des zu zeichnenden Elements. „ initFrom() “ setzt es auf das Begrenzungsrechteck des Widgets (QWidget::rect()). |
| direction | Die Layoutrichtung, ein Wert aus der Enumeration „ Qt::LayoutDirection “. |
| palette | Die beim Zeichnen des Elements zu verwendende „ QPalette “. „ initFrom() “ setzt diesen Wert auf die Palette des Widgets (QWidget::palette()). |
| fontMetrics | Die „ QFontMetrics “, die beim Zeichnen von Text auf dem Widget verwendet werden soll. |
| styleObject | Das Objekt, das die Option beschreibt, in der Regel das Widget. Stile verwenden es, um den Animationszustand zu speichern. |
Die komplexen Stiloptionen (Klassen, die von ` QStyleOptionComplex` erben) verfügen über zwei weitere Variablen: ` subControls ` und ` activeSubControls`. Beide sind ODER-Kombinationen von ` QStyle::SubControl `-Werten. Sie geben an, aus welchen Unterelementen das komplexe Steuerelement besteht und welche davon derzeit aktiv sind.
QStyle-Funktionen
QStyle definiert drei Funktionen zum Zeichnen der primitiven, Steuerelement- und komplexen Elemente: ` drawPrimitive()`, ` drawControl()` und ` drawComplexControl()`. Sie nehmen die unter „Style-Elemente“ aufgeführten Argumente entgegen.
Nicht alle Widgets übergeben einen Zeiger auf sich selbst. Wenn die an die Funktion übergebene Stiloption nicht die benötigten Informationen enthält, prüfen Sie die Widget-Implementierung, um festzustellen, ob das Widget sich selbst übergibt.
QStyle bietet außerdem Hilfsfunktionen zum Zeichnen von Elementen. ` drawItemText()` zeichnet Text innerhalb eines angegebenen Rechtecks und nimmt ein ` QPalette ` als Parameter entgegen. ` drawItemPixmap()` richtet eine Pixmap innerhalb eines angegebenen Begrenzungsrechtecks aus.
Andere QStyle -Funktionen führen Berechnungen für die Zeichenfunktionen durch. Die Widgets nutzen sie ebenfalls, um Größenhinweise und Begrenzungsrechtecke zu berechnen, wenn sie selbst mehrere Stilelemente zeichnen. Diese Funktionen nehmen in der Regel dieselben Argumente entgegen wie die Zeichenfunktionen.
- subElementRect() nimmt einen „ SubElement “-Wert entgegen und berechnet das Begrenzungsrechteck eines Unterelements. Der Stil nutzt diese Funktion, um zu ermitteln, wo die verschiedenen Teile eines Elements gezeichnet werden sollen. Wenn Sie einen neuen Stil erstellen, können Sie die Positionen der Unterelemente der Basisklasse wiederverwenden.
- subControlRect() berechnet die Begrenzungsrechtecke der Untersteuerelemente in komplexen Steuerelementen. Wenn Sie einen neuen Stil implementieren, implementieren Sie diese Funktion für die Rechtecke neu, die sich von denen der Basisklasse unterscheiden.
- pixelMetric() gibt eine Pixelmetrik zurück, eine stilabhängige Größe, die in Bildschirmpixeln angegeben wird. Als Wert wird ein Element der Enumeration „ PixelMetric “ angenommen. Pixelmetriken müssen keine statischen Maße sein; Sie können sie anhand der Stiloption berechnen.
- sizeFromContents() gibt die Größe eines Widgets für eine bestimmte Inhaltsgröße zurück. Widgets verwenden diesen Wert, um ihre Größenhinweise zu berechnen.
- hitTestComplexControl() gibt das Unterelement zurück, über dem sich der Mauszeiger in einem komplexen Steuerelement befindet. In der Regel erfolgt dies durch Aufruf von ` subControlRect()` zum Abrufen der Begrenzungsrechtecke der Unterelemente und durch Ermitteln desjenigen, das die Position des Cursors enthält.
QStyle verfügt außerdem über die Funktionen ` polish()` und ` unpolish()`. Qt führt bei jedem Widget vor der ersten Darstellung sowie bei jeder Stiländerung eine „Polishing“-Phase durch und hebt diese wieder auf, wenn sich der Stil ändert oder das Widget zerstört wird. Verwenden Sie diese Funktionen, um Attribute an den Widgets festzulegen oder andere Aufgaben auszuführen, die Ihr Stil erfordert. Wenn Sie beispielsweise wissen müssen, wann sich der Mauszeiger über einem Widget befindet, setzen Sie das Widget-Attribut „ WA_Hover “ in „ polish() “. Das Widget setzt daraufhin „ State_MouseOver “ in seinen Stiloptionen. Überladungen von „ polish() “ ermöglichen es dem Stil außerdem, die „ QApplication “ vorzubereiten und die Anwendungspalette anzupassen; siehe „Die Palette“.
Schließlich verfügt „ QStyle “ über statische Hilfsfunktionen für häufige und schwierige Aufgaben. „ sliderPositionFromValue()“ und „ sliderValueFromPosition()“ wandeln zwischen Schiebereglerwerten und Pixelpositionen um. „ visualRect()“, „ visualPos()“ und „ visualAlignment()“ übersetzen logische Koordinaten und Ausrichtungen in ihre gespiegelten Entsprechungen in Layouts von rechts nach links, und „ alignedRect()“ richtet ein Rechteck für die aktuelle Richtung aus. Weitere Informationen finden Sie unter „ Right-to-Left Desktops “ in der Dokumentation zur Klasse „ QStyle “.
Wenn Sie die virtuellen Funktionen von ` QStyle ` neu implementieren, behandeln Sie die Elemente, die sich von der Basisklasse unterscheiden, und rufen Sie für alles andere die Implementierung der Basisklasse auf.
Die Palette
Jeder Stil zeichnet mit einer Palette von Pinseln, die von ` QPalette` bereitgestellt wird. Für jeden Widget-Zustand gibt es einen Farbsatz, eine „ QPalette::ColorGroup “: „active“ für Widgets im Fenster, das den Tastaturfokus hat, „inactive“ für Widgets in anderen Fenstern und „disabled“ für deaktivierte Widgets. Die Zustandsflags „ State_Active “ und „ State_Enabled “ geben an, welche Gruppe verwendet werden soll. Jede Gruppe enthält die Farbrollen, die in ` QPalette::ColorRole ` definiert sind. Die Rollen beschreiben die Situationen, für die die Farben vorgesehen sind, wie zum Beispiel das Einfärben von Widget-Hintergründen, Text oder Schaltflächen.
Jeder Stil legt fest, wie die Farbrollen verwendet werden. Wenn der Stil beispielsweise Farbverläufe verwendet, kann er eine Palettenfarbe mit ` QColor::darker()` und ` QColor::lighter()` abdunkeln oder aufhellen, um den Farbverlauf zu erzeugen. Im Allgemeinen gilt: Wenn Sie einen Pinsel benötigen, den die Palette nicht bereitstellt, leiten Sie ihn von einem vorhandenen Pinsel ab.
Wenn Sie einen Stil für die Anwendung festlegen, erstellt Qt die Anwendungspalette anhand der Funktion ` standardPalette()` des Stils, lässt das Plattform-Thema die bereitgestellten Rollen überschreiben und übergibt das Ergebnis an ` QStyle::polish()`. Implementieren Sie diese Überladung neu, um die Farben anzupassen, die Ihr Stil benötigt. Qt überschreibt keine Palette, die die Anwendung explizit mit ` QApplication::setPalette()` festgelegt hat.
Farbwerte sollten nicht fest codiert werden. Anwendungen und einzelne Widgets können ihre eigene Farbpalette festlegen, und ein Stil, der aus dieser Palette zeichnet, passt sich daran an. Er erhält zudem ohne zusätzlichen Code eine helle und eine dunkle Variante aus zwei Farbpaletten. Der Qt-Stil „Fusion“ funktioniert auf diese Weise:
|
|
Ein Stil muss nicht mit jeder denkbaren Palette gut aussehen, sollte aber die ihm zugewiesene Palette berücksichtigen.
Elementansichten
Delegaten zeichnen die Elemente in Elementansichten. Der Standard-Delegat von Qt, ` QStyledItemDelegate`, zeichnet ` CE_ItemViewItem ` und berechnet die Elementgrößen mit ` CT_ItemViewItem`, sodass ein Stil auch ohne zugehörigen Delegaten das Aussehen der Elemente steuert. Der Stil zeichnet die Kopfzeilen der Elementansichten, die Baumzweig-Indikatoren und die Zeilenhintergründe direkt. Um neue Datentypen oder Elementdatenrollen zu unterstützen, benötigen Sie einen benutzerdefinierten Delegaten; siehe Modell-View-Programmierung.
Hinweise zur Implementierung
Wenn Sie einen Stil implementieren, lesen Sie den Code der Widgets und der Basisklasse. Die Widgets nutzen den Stil auf unterschiedliche Weise, und die Implementierung der Basisklasse kann den Zustand der Zeichnung beeinflussen, beispielsweise indem sie den Zustand von ` QPainter ` ändert, ohne ihn wiederherzustellen, oder indem sie einige Elemente zeichnet, ohne die entsprechenden Pixelmaße und Unterelemente zu verwenden.
Ändern Sie die vorgeschlagene Größe von Widgets in ` sizeFromContents()` nur, wenn es unbedingt notwendig ist; überlassen Sie dies der Implementierung von ` QCommonStyle `. Wenn Sie Änderungen vornehmen, halten Sie diese gering. Die Anwendungsentwicklung wird erschwert, wenn sich das Layout der Widgets zwischen den Stilen erheblich unterscheidet.
Testen Sie Ihren Stil mit der Befehlszeilenoption „ -reverse “ oder mit „ QGuiApplication::setLayoutDirection()“, damit asymmetrische Elemente auch in einem Rechts-nach-Links-Layout korrekt dargestellt werden.
Siehe auch „ QStyle“ , „ QStyleOption “, „ QStylePainter “, „Widget Style Reference“ und „Styling a Checkbox: A Walkthrough“.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.

