Stile und stilabhängige Widgets

Stile (Klassen, die von QStyle erben) zeichnen im Namen von Widgets und kapseln das Aussehen einer grafischen Benutzeroberfläche (GUI). Die Klasse QStyle ist eine abstrakte Basisklasse, die das Erscheinungsbild einer grafischen Benutzeroberfläche kapselt. Die in Qt eingebauten Widgets verwenden diese Klasse, um fast alle Zeichnungen auszuführen und sicherzustellen, dass sie genau wie die entsprechenden nativen Widgets aussehen.

Qt wird mit einer Auswahl an eingebauten Stilen geliefert. Bestimmte Stile sind nur auf bestimmten Plattformen verfügbar. Benutzerdefinierte Stile werden als Plugins zur Verfügung gestellt oder indem man eine Instanz einer bestimmten Stilklasse mit QStyleFactory::create() erzeugt und mit QApplication::setStyle() einstellt.

Anpassen eines Stils

Um einen vorhandenen Stil anzupassen, erben Sie QProxyStyle und implementieren die gewünschten virtuellen Methoden neu. QProxyStyle ermöglicht die Angabe eines bestimmten Basisstils, oder es wird automatisch der Anwendungsstil verwendet, wenn der Basisstil nicht angegeben wird. Ersteres gibt volle Kontrolle über den Basisstil und funktioniert am besten, wenn die Anpassung ein bestimmtes Stilverhalten erwartet, während letzteres einen plattformunabhängigen Weg zur Anpassung des Anwendungsstils bietet, der standardmäßig den nativen Plattformstil verwendet.

Implementieren eines benutzerdefinierten Stils

QCommonStyle bietet eine bequeme Basis für vollständige Implementierungen benutzerdefinierter Stile. Der Ansatz ist derselbe wie bei QProxyStyle, nur dass man stattdessen QCommonStyle erbt und die entsprechenden virtuellen Methoden neu implementiert. Die Implementierung eines vollständigen benutzerdefinierten Stils ist etwas kompliziert, weshalb wir diesen Überblick geben. Wir führen Schritt für Schritt aus, wie einzelne Qt Widgets gestaltet werden können. Wir werden die virtuellen Funktionen, Mitgliedsvariablen und Aufzählungen von QStyle untersuchen.

Der Teil dieses Dokuments, der sich nicht mit dem Styling einzelner Widgets befasst, sollte der Reihe nach gelesen werden, da spätere Abschnitte in der Regel von den früheren abhängen. Die Beschreibung der Widgets kann bei der Implementierung eines Stils als Referenz verwendet werden. In einigen Fällen müssen Sie jedoch den Qt-Quellcode zu Rate ziehen. Die Reihenfolge des Styling-Prozesses sollte nach der Lektüre dieses Dokuments klar werden, was Ihnen helfen wird, den relevanten Code zu finden.

Um stilbewusste Widgets zu entwickeln (d.h. Widgets, die sich an den Stil anpassen, in dem sie gezeichnet werden), müssen Sie sie unter Verwendung des aktuellen Stils zeichnen. Dieses Dokument zeigt, wie Widgets gezeichnet werden und welche Möglichkeiten der Stil ihnen gibt.

Klassen für das Widget-Styling

Diese Klassen werden verwendet, um das Aussehen und den Stil einer Anwendung anzupassen.

QColor

Farben basierend auf RGB-, HSV- oder CMYK-Werten

QColorSpace

Abstraktion von Farbräumen

QColorTransform

Transformation zwischen Farbräumen

QCommonStyle

Kapselt das gemeinsame Look and Feel einer GUI

QCursor

Mauszeiger mit beliebiger Form

QFont

Spezifiziert eine Abfrage für eine Schriftart, die zum Zeichnen von Text verwendet wird

QFontDatabase

Informationen über die im zugrunde liegenden Fenstersystem verfügbaren Schriftarten

QFontInfo

Allgemeine Informationen über Schriftarten

QGraphicsAnchor

Repräsentiert einen Anker zwischen zwei Elementen in einem QGraphicsAnchorLayout

QGraphicsAnchorLayout

Layout, in dem man Widgets in der Grafikansicht miteinander verankern kann

QPalette

Enthält Farbgruppen für jeden Widget-Zustand

QStyle

Abstrakte Basisklasse, die das Aussehen einer GUI kapselt

QStyleFactory

Erzeugt QStyle-Objekte

QStyleHintReturn

Style-Hinweise, die mehr als grundlegende Datentypen zurückgeben

QStyleHintReturnMask

Style-Hinweise, die eine QRegion zurückgeben

QStyleHintReturnVariant

Style-Hinweise, die eine QVariant zurückgeben

QStyleOption

Speichert die von QStyle-Funktionen verwendeten Parameter

QStylePainter

Convenience-Klasse zum Zeichnen von QStyle-Elementen innerhalb eines Widgets

Die QStyle-Implementierung

Die API von QStyle enthält Funktionen zum Zeichnen der Widgets, statische Hilfsfunktionen für häufige und schwierige Aufgaben (z. B. Berechnung der Position von Schiebegriffen) und Funktionen für die verschiedenen Berechnungen, die während des Zeichnens erforderlich sind (z. B. für die Widgets zur Berechnung ihrer Größenhinweise). Der Stil hilft auch einigen Widgets bei der Gestaltung ihres Inhalts. Darüber hinaus wird eine QPalette erstellt, die QBrushes zum Zeichnen enthält.

QStyle zeichnet grafische Elemente; ein Element ist ein Widget oder ein Widgetteil wie eine Drucktastenschräge, ein Fensterrahmen oder eine Bildlaufleiste. Die meisten Zeichenfunktionen nehmen nun vier Argumente entgegen:

  • einen Enum-Wert, der angibt, welches grafische Element gezeichnet werden soll
  • eine QStyleOption, die angibt, wie und wo das Element gerendert werden soll
  • eine QPainter, die zum Zeichnen des Elements verwendet werden soll
  • eine QWidget, auf der die Zeichnung ausgeführt wird (optional)

Wenn ein Widget einen Stil auffordert, ein Element zu zeichnen, stellt es dem Stil eine QStyleOption zur Verfügung, die eine Klasse ist, die die für das Zeichnen notwendigen Informationen enthält. Dank QStyleOption ist es möglich, QStyle Widgets zeichnen zu lassen, ohne irgendeinen Code für das Widget einzubinden. Dies macht es möglich, die Zeichenfunktionen von QStyle auf jedem Malgerät zu verwenden, d.h. Sie können eine Combobox auf jedem Widget zeichnen, nicht nur auf einem QComboBox.

Das Widget wird als letztes Argument übergeben, für den Fall, dass der Stil es benötigt, um spezielle Effekte auszuführen (wie z. B. animierte Standardschaltflächen unter macOS), aber es ist nicht zwingend erforderlich.

Im Laufe dieses Abschnitts werden wir uns die Stilelemente, die Stiloptionen und die Funktionen von QStyle ansehen. Abschließend beschreiben wir, wie die Palette verwendet wird.

Elemente in Elementansichten werden von Delegierten in Qt gezeichnet. Die Kopfzeilen der Elementansichten werden weiterhin durch den Stil gezeichnet. Der Standarddelegierte von Qt, QStyledItemDelegate, zeichnet seine Elemente teilweise durch den aktuellen Stil; er zeichnet die Kontrollkästchenindikatoren und berechnet die Begrenzungsrechtecke für die Elemente, aus denen das Element besteht. In diesem Dokument wird nur beschrieben, wie man eine QStyle Unterklasse implementiert. Wenn Sie Unterstützung für andere Datentypen als die von QStyledItemDelegate unterstützten hinzufügen möchten, müssen Sie einen eigenen Delegaten implementieren. Beachten Sie, dass Delegaten für jedes einzelne Widget programmatisch festgelegt werden müssen (d.h. Standarddelegaten können nicht als Plugins bereitgestellt werden).

Die Stilelemente

Ein Stilelement ist ein grafischer Teil einer GUI. Ein Widget besteht aus einer Hierarchie (oder einem Baum) von Stilelementen. Wenn ein Stil beispielsweise die Anforderung erhält, eine Drucktaste zu zeichnen (z. B. von QPushButton), zeichnet er eine Beschriftung (Text und Symbol), eine Tastenschräge und einen Fokusrahmen. Die Tastenschräge wiederum besteht aus einem Rahmen um die Schräge und zwei weiteren Elementen, auf die wir später noch eingehen werden. Nachfolgend sehen Sie eine konzeptionelle Darstellung des Elementbaums für Drucktasten. Die tatsächliche Struktur von QPushButton werden wir sehen, wenn wir die einzelnen Widgets durchgehen.

Widgets werden nicht notwendigerweise gezeichnet, indem der Stil aufgefordert wird, nur ein Element zu zeichnen. Widgets können mehrere Aufrufe an die Formatvorlage machen, um verschiedene Elemente zu zeichnen. Ein Beispiel ist QTabWidget, das seine Registerkarten und den Rahmen einzeln zeichnet.

Es gibt drei Elementtypen: primitive Elemente, Steuerelemente und komplexe Steuerelemente. Die Elemente werden durch die Enums ComplexControl, ControlElement und PrimitiveElement definiert. Die Werte jedes Element-Enums haben ein Präfix, um ihren Typ zu identifizieren: CC_ für komplexe Elemente, CE_ für Steuerelemente und PE_ für primitive Elemente. In den folgenden drei Abschnitten werden wir sehen, was die verschiedenen Elemente definiert und Beispiele für Widgets sehen, die sie verwenden.

Die Klassenbeschreibung QStyle enthält eine Liste dieser Elemente und ihrer Rolle bei der Gestaltung von Widgets. Wir werden sehen, wie sie verwendet werden, wenn wir einzelne Widgets gestalten.

Primitive Elemente

Primitive Elemente sind GUI-Elemente, die häufig von mehreren Widgets verwendet werden. Beispiele hierfür sind Rahmen, Schaltflächenschrägen und Pfeile für Drehfelder, Bildlaufleisten und Kombinationsfelder. Primitive Elemente können nicht für sich alleine existieren: Sie sind immer Teil eines größeren Konstrukts. Sie nehmen nicht an der Interaktion mit dem Benutzer teil, sondern sind passive Dekorationen in der GUI.

Steuerelemente

Ein Steuerelement führt eine Aktion aus oder zeigt dem Benutzer Informationen an. Beispiele für Steuerelemente sind Drucktasten, Kontrollkästchen und Kopfbereiche in Tabellen und Baumansichten. Steuerelemente sind nicht notwendigerweise vollständige Widgets wie Drucktasten, sondern können auch Widget-Teile sein, wie z. B. Registerkarten und Schieberegler in der Bildlaufleiste. Sie unterscheiden sich von primitiven Elementen dadurch, dass sie nicht passiv sind, sondern eine Funktion in der Interaktion mit dem Benutzer erfüllen. Steuerelemente, die aus mehreren Elementen bestehen, verwenden oft den Stil, um die Begrenzungsrechtecke der Elemente zu berechnen. Die verfügbaren Unterelemente werden durch das SubElement enum definiert. Diese Aufzählung wird nur für die Berechnung von Begrenzungsrechtecken verwendet; Unterelemente sind keine grafischen Elemente, die wie primitive, Steuerelemente 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 anfasst und welche Tasten er drückt. Dies hängt davon ab, auf welchem Untersteuerelement (falls vorhanden) sich die Maus befindet oder auf das sie gedrückt wird. Beispiele für komplexe Steuerelemente sind Bildlaufleisten und Kombinationsfelder. Bei einer Bildlaufleiste können Sie den Schieberegler mit der Maus verschieben und die Tasten zum Hoch- und Runterzählen drücken. Die verfügbaren Untersteuerelemente werden durch die Aufzählung SubControl definiert.

Zusätzlich zum Zeichnen muss der Stil die Widgets mit Informationen darüber versorgen, auf welchem Untersteuerelement (falls vorhanden) ein Mausklick erfolgt ist. Zum Beispiel muss QScrollBar wissen, ob der Benutzer den Schieberegler, die Schiebereglerrille oder eine der Schaltflächen gedrückt hat.

Beachten Sie, dass Untersteuerelemente nicht dasselbe sind wie die im vorherigen Abschnitt beschriebenen Steuerelemente. Sie können den Stil nicht verwenden, um ein Untersteuerelement zu zeichnen; der Stil berechnet nur das Begrenzungsrechteck, in dem das Untersteuerelement gezeichnet werden soll. Es ist jedoch üblich, dass komplexe Elemente Steuerelemente und primitive Elemente verwenden, um ihre Untersteuerelemente zu zeichnen. Dies ist ein Ansatz, der häufig von den eingebauten Stilen in Qt und auch dem Java-Stil verwendet wird. Der Java-Stil verwendet zum Beispiel PE_IndicatorCheckBox, um das Kontrollkästchen in Gruppenrahmen zu zeichnen (das ein Untersteuerelement von CC_GroupBox ist). Einige Untersteuerelemente haben ein entsprechendes Steuerelement, z. B. der Schieberegler der Bildlaufleiste (SC_SCrollBarSlider und CE_ScrollBarSlider).

Andere QStyle-Aufgaben

Die Stilelemente und Widgets verwenden, wie bereits erwähnt, den Stil, um die Begrenzungsrechtecke der Unterelemente und Untersteuerelemente zu berechnen. Pixel-Metriken, die stilabhängige Größen in Bildschirm-Pixeln sind, werden auch für Messungen beim Zeichnen verwendet. Die verfügbaren Rechtecke und Pixelmetriken werden durch drei Enums in QStyle dargestellt: SubElement, SubControl und PixelMetric. Die Werte der Enums können leicht identifiziert werden, da sie mit SE_, SC_ und PM_ beginnen.

Der Stil enthält auch eine Reihe von Stilhinweisen, die als Werte in der Aufzählung StyleHint dargestellt werden. Nicht alle Widgets haben die gleiche Funktionalität und das gleiche Aussehen in den verschiedenen Stilen. Wenn zum Beispiel die Menüpunkte in einem Menü nicht in eine einzige Spalte auf dem Bildschirm passen, unterstützen einige Stile das Scrollen, während andere mehr als eine Spalte zeichnen, um alle Punkte unterzubringen.

Ein Stil verfügt in der Regel über eine Reihe von Standardbildern (z. B. ein Warn-, ein Frage- und ein Fehlerbild) für Meldungsfelder, Dateidialoge usw. QStyle bietet das Enum StandardPixmap. Seine Werte repräsentieren die Standardbilder. Die Widgets von Qt verwenden diese, wenn Sie also einen benutzerdefinierten Stil implementieren, sollten Sie die Bilder bereitstellen, die von dem implementierten Stil verwendet werden.

Der Stil berechnet die Abstände zwischen Widgets in Layouts. Es gibt zwei Möglichkeiten, wie der Stil diese Berechnungen durchführen kann. Sie können PM_LayoutHorizontalSpacing und PM_LayoutVerticalSpacing setzen, wie es der Java-Stil tut (durch QCommonStyle). Alternativ dazu können Sie QStyle::layoutSpacing() und QStyle::layoutSpacingImplementation() implementieren, wenn Sie mehr Kontrolle über diesen Teil des Layouts benötigen. In diesen Funktionen können Sie die Abstände auf der Grundlage von Kontrolltypen (QSizePolicy::ControlType) für verschiedene Größenrichtlinien (QSizePolicy::Policy) und auch die Stiloption für das betreffende Widget berechnen.

Stil-Optionen

Die Unterklassen von QStyleOption enthalten alle Informationen, die zur Gestaltung der einzelnen Elemente notwendig sind. Stiloptionen werden instanziiert - normalerweise auf dem Stack - und vom Aufrufer der Funktion QStyle ausgefüllt. Je nachdem, was gezeichnet wird, erwartet der Stil eine andere Klasse von Stiloptionen. Zum Beispiel erwartet das Element QStyle::PE_FrameFocusRect ein Argument QStyleOptionFocusRect, und es ist möglich, benutzerdefinierte Unterklassen zu erstellen, die ein benutzerdefinierter Stil verwenden kann. Die Stiloptionen behalten aus Leistungsgründen öffentliche Variablen.

Die Widgets können sich in einer Reihe von verschiedenen Zuständen befinden, die durch das State enum definiert sind. Einige der Statusflags haben je nach Widget unterschiedliche Bedeutungen, aber andere sind für alle Widgets gleich, wie State_Disabled. Es ist QStyleOption, das die gemeinsamen Zustände mit QStyleOption::initFrom() setzt; die übrigen Zustände werden von den einzelnen Widgets gesetzt.

Vor allem die Stiloptionen enthalten die Palette und die Begrenzungsrechtecke der zu zeichnenden Widgets. Die meisten Widgets haben spezielle Stiloptionen. QPushButton und QCheckBox beispielsweise verwenden QStyleOptionButton als Stiloption, die den Text, das Symbol und die Größe des Symbols enthält. Der genaue Inhalt aller Optionen wird beschrieben, wenn wir die einzelnen Widgets durchgehen.

Bei der Neuimplementierung von QStyle -Funktionen, die einen QStyleOption -Parameter benötigen, müssen Sie QStyleOption oft in eine Unterklasse umwandeln (z. B. QStyleOptionFocusRect). Zur Sicherheit können Sie qstyleoption_cast() verwenden, um sicherzustellen, dass der Zeigertyp korrekt ist. Wenn das Objekt nicht vom richtigen Typ ist, gibt qstyleoption_cast() nullptr zurück. Ein Beispiel:

const QStyleOptionFocusRect *focusRectOption =
        qstyleoption_cast<const QStyleOptionFocusRect *>(option);
if (focusRectOption) {
    ...
}

Der folgende Codeschnipsel veranschaulicht, wie QStyle verwendet wird, um das Fokusrechteck aus dem paintEvent() eines benutzerdefinierten Widgets zu zeichnen:

void MyWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    ...

    QStyleOptionFocusRect option(1);
    option.init(this);
    option.backgroundColor = palette().color(QPalette::Window);

    style().drawPrimitive(QStyle::PE_FrameFocusRect, &option, &painter,
                          this);
}

Das nächste Beispiel zeigt, wie man von einem vorhandenen Stil ableitet, um das Aussehen eines grafischen Elements anzupassen:

class CustomStyle : public QProxyStyle
{
    Q_OBJECT

public:
    CustomStyle(const QWidget *widget);
    ~CustomStyle() {}

    void drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                       QPainter *painter, const QWidget *widget) const override;
};

void CustomStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                                QPainter *painter, const QWidget *widget) const
{
    if (element == PE_IndicatorSpinUp || element == PE_IndicatorSpinDown) {
        QPolygon points(3);
        int x = option->rect.x();
        int y = option->rect.y();
        int w = option->rect.width() / 2;
        int h = option->rect.height() / 2;
        x += (option->rect.width() - w) / 2;
        y += (option->rect.height() - h) / 2;

        if (element == PE_IndicatorSpinUp) {
            points[0] = QPoint(x, y + h);
            points[1] = QPoint(x + w, y + h);
            points[2] = QPoint(x + w / 2, y);
        } else { // PE_SpinBoxDown
            points[0] = QPoint(x, y);
            points[1] = QPoint(x + w, y);
            points[2] = QPoint(x + w / 2, y + h);
        }

        if (option->state & State_Enabled) {
            painter->setPen(option->palette.mid().color());
            painter->setBrush(option->palette.buttonText());
        } else {
            painter->setPen(option->palette.buttonText().color());
            painter->setBrush(option->palette.mid());
        }
        painter->drawPolygon(points);
    } else {
        QProxyStyle::drawPrimitive(element, option, painter, widget);
    }
}

QStyle Funktionen

Die Klasse QStyle definiert drei Funktionen für das Zeichnen von primitiven, Kontroll- und komplexen Elementen: drawPrimitive(), drawControl(), und drawComplexControl(). Die Funktionen nehmen die folgenden Parameter entgegen:

  • den Enum-Wert des zu zeichnenden Elements.
  • eine QStyleOption, die die zum Zeichnen des Elements erforderlichen Informationen enthält.
  • ein QPainter, mit dem das Element gezeichnet werden soll.
  • einen Zeiger auf ein QWidget, normalerweise das Widget, auf dem das Element gezeichnet wird.

Nicht alle Widgets senden einen Zeiger auf sich selbst. Wenn die an die Funktion gesendete Stiloption nicht die benötigten Informationen enthält, sollten Sie die Implementierung des Widgets überprüfen, um zu sehen, ob es einen Zeiger auf sich selbst sendet.

Die Klasse QStyle bietet auch Hilfsfunktionen, die beim Zeichnen der Elemente verwendet werden. Die Funktion drawItemText() zeichnet Text innerhalb eines bestimmten Rechtecks und nimmt QPalette als Parameter an. Die Funktion drawItemPixmap() hilft bei der Ausrichtung einer Pixmap innerhalb eines bestimmten Begrenzungsrechtecks.

Andere Funktionen von QStyle führen verschiedene Berechnungen für die Funktionen durch, die das Zeichnen übernehmen. Die Widgets verwenden diese Funktionen auch zur Berechnung von Größenhinweisen und Begrenzungsrechtecken, wenn sie selbst mehrere Stilelemente zeichnen. Wie die Funktionen, die Elemente zeichnen, nehmen auch die Hilfsfunktionen in der Regel die gleichen Argumente an.

  • Die Funktion subElementRect() nimmt einen SubElement enum-Wert und berechnet ein Begrenzungsrechteck für ein Unterelement. Der Stil verwendet diese Funktion, um zu wissen, wo die verschiedenen Teile eines Elements zu zeichnen sind. Dies geschieht hauptsächlich aus Gründen der Wiederverwendung; wenn Sie einen neuen Stil erstellen, können Sie die gleiche Position der Unterelemente wie die Oberklasse verwenden.
  • Die Funktion subControlRect() wird verwendet, um Begrenzungsrechtecke für Unterelemente in komplexen Steuerelementen zu berechnen. Wenn Sie einen neuen Stil implementieren, müssen Sie subControlRect() neu implementieren und die Rechtecke berechnen, die sich von denen der Superklasse unterscheiden.
  • Die Funktion pixelMetric() gibt eine Pixelmetrik zurück, die eine stilabhängige Größe in Bildschirm-Pixeln angibt. Sie nimmt einen Wert aus dem PixelMetric enum und gibt das korrekte Maß zurück. Beachten Sie, dass Pixelmetriken nicht unbedingt statische Maße sein müssen, sondern z. B. mit der Option style berechnet werden können.
  • Die Funktion hitTestComplexControl() gibt das Unterelement zurück, über dem sich der Mauszeiger in einem komplexen Steuerelement befindet. Normalerweise ist es einfach, mit subControlRect() die Begrenzungsrechtecke der Untersteuerelemente zu ermitteln und dann zu sehen, welches Rechteck die Position des Mauszeigers enthält.

QStyle hat auch die Funktionen polish() und unpolish(). Alle Widgets werden an die Funktion polish() gesendet, bevor sie angezeigt werden, und an unpolish(), wenn sie ausgeblendet werden. Sie können diese Funktionen verwenden, um Attribute für die Widgets zu setzen oder andere Arbeiten auszuführen, die für Ihren Stil erforderlich sind. Wenn Sie z. B. wissen müssen, wann die Maus über dem Widget schwebt, müssen Sie das Widget-Attribut WA_Hover setzen. Das Statusflag State_MouseOver wird dann in den Stiloptionen des Widgets gesetzt.

QStyle hat ein paar statische Hilfsfunktionen, die einige häufige und schwierige Aufgaben erledigen. Sie können die Position eines Schiebereglergriffs aus dem Wert des Schiebereglers berechnen und Rechtecke transformieren und Text unter Berücksichtigung umgekehrter Layouts zeichnen; weitere Details finden Sie in der Dokumentation der Klasse QStyle.

Der übliche Ansatz, wenn man die virtuellen Funktionen von QStyle neu implementiert, ist die Arbeit an Elementen, die sich von der Superklasse unterscheiden; für alle anderen Elemente können Sie einfach die Implementierung der Superklasse verwenden.

Die Palette

Jeder Stil bietet eine Farbpalette ( QBrush ), die zum Zeichnen der Widgets verwendet werden sollte. Es gibt einen Satz von Farben für die verschiedenen Widgetzustände (QPalette::ColorGroup): aktiv (Widgets im Fenster, die den Tastaturfokus haben), inaktiv (Widgets, die für andere Fenster verwendet werden) und deaktiviert (Widgets, die deaktiviert sind). Die Zustände können durch Abfrage der Statusflags State_Active und State_Enabled ermittelt werden. Jeder Satz enthält bestimmte Farbrollen, die durch das QPalette::ColorRole enum gegeben sind. Die Rollen beschreiben, in welchen Situationen die Farben verwendet werden sollen (z.B. zum Malen von Widgethintergründen, Text oder Schaltflächen).

Wie die Farbrollen verwendet werden, hängt von dem Stil ab. Wenn der Stil zum Beispiel Farbverläufe verwendet, kann man eine Palettenfarbe verwenden und sie mit QColor::darker() und QColor::lighter() dunkler oder heller machen, um den Farbverlauf zu erzeugen. Wenn Sie einen Pinsel benötigen, der nicht in der Palette enthalten ist, sollten Sie versuchen, ihn von einer Palette abzuleiten.

QPaletteDie Palette, die die Palette bereitstellt, speichert Farben für verschiedene Widget-Zustände und Farbrollen. Die Palette für einen Stil wird von standardPalette() zurückgegeben. Die Standardpalette wird nicht automatisch installiert, wenn ein neuer Stil für die Anwendung (QApplication::setStyle()) oder das Widget (QWidget::setStyle()) festgelegt wird. Sie müssen die Palette also selbst mit (QApplication::setPalette()) oder (QWidget::setPalette()) festlegen.

Es wird nicht empfohlen, Farben fest zu kodieren, da Anwendungen und einzelne Widgets ihre eigene Palette setzen und auch die Palette ihres Stils zum Zeichnen verwenden können. Beachten Sie, dass keines der Qt Widgets seine eigene Palette festlegt. Der Java-Stil kodiert einige Farben fest, aber nur als eine Entscheidung des Autors; es wird nicht empfohlen. Natürlich ist es nicht beabsichtigt, dass der Stil mit jeder Palette gut aussieht.

Probleme bei der Implementierung

Bei der Implementierung von Stilen sind mehrere Aspekte zu berücksichtigen. Wir werden hier einige Hinweise und Ratschläge zur Implementierung geben.

Bei der Implementierung von Stilen ist es notwendig, den Code der Widgets und den Code der Basisklasse und ihrer Vorgänger zu durchschauen. Der Grund dafür ist, dass die Widgets den Stil unterschiedlich verwenden, weil die Implementierung in den virtuellen Funktionen der verschiedenen Stile den Zustand der Zeichnung beeinflussen kann (z. B. durch Änderung des Zustands von QPainter, ohne ihn wiederherzustellen, und durch Zeichnen einiger Elemente ohne Verwendung der entsprechenden Pixelmetriken und Unterelemente).

Es wird empfohlen, dass die Stile die vorgeschlagene Größe der Widgets nicht mit der Funktion QStyle::sizeFromContents() ändern, sondern dies stattdessen der Implementierung von QCommonStyle überlassen. Wenn Änderungen vorgenommen werden müssen, sollten Sie versuchen, diese klein zu halten; die Anwendungsentwicklung kann schwierig werden, wenn das Layout der Widgets in den verschiedenen Stilen erheblich anders aussieht.

Java-Stil

Wir haben einen Stil implementiert, der dem Standard-Look-and-Feel von Java (früher bekannt als Metal) ähnelt. Wir haben dies getan, weil es relativ einfach zu implementieren ist und wir einen Stil für dieses Übersichtsdokument erstellen wollten. Um ihn einfach und nicht zu umfangreich zu halten, haben wir den Stil etwas vereinfacht, aber Qt ist durchaus in der Lage, eine exakte Kopie des Stils zu erstellen. Es gibt jedoch keine konkreten Pläne, den Stil als Teil von Qt zu implementieren.

In diesem Abschnitt werden wir einen Blick auf einige Implementierungsprobleme werfen. Schließlich werden wir ein vollständiges Beispiel für das Styling eines Java-Widgets sehen. Wir werden den Java-Stil weiterhin im gesamten Dokument für Beispiele und Widget-Bilder verwenden. Die Implementierung selbst ist etwas kompliziert, und es ist nicht beabsichtigt, dass Sie sie durchlesen.

Entwurf und Implementierung

Der erste Schritt beim Entwurf des Stils war die Auswahl der Basisklasse. Wir haben uns für die Unterklasse QCommonStyle entschieden. Diese Klasse implementiert die meisten Funktionen, die wir benötigen, abgesehen vom eigentlichen Zeichnen.

Der Stil ist in einer einzigen Klasse implementiert. Wir haben dies getan, weil wir es bequem finden, den gesamten Code in einer Datei zu halten. Außerdem ist es ein Vorteil im Hinblick auf die Optimierung, da wir weniger Objekte instanziieren. Wir halten auch die Anzahl der Funktionen auf ein Minimum, indem wir Schalter verwenden, um zu bestimmen, welches Element in den Funktionen gezeichnet werden soll. Dies führt zu großen Funktionen, aber da wir den Code für jedes Element in die Schalter aufteilen, sollte der Code immer noch leicht zu lesen sein.

Beschränkungen und Unterschiede zu Java

Wir haben nicht jedes Element im Java-Stil vollständig implementiert. Auf diese Weise haben wir den Umfang und die Komplexität des Codes reduziert. Im Allgemeinen war der Stil als praktisches Beispiel für dieses Stil-Übersichtsdokument gedacht, und nicht als Teil von Qt selbst.

Nicht alle Widgets haben jeden Zustand implementiert. Dies gilt für Zustände, die häufig vorkommen, z.B. State_Disabled. Jeder Zustand ist jedoch für mindestens ein Widget implementiert.

Wir haben nur Ticks unterhalb des Schiebereglers implementiert. Flache Drucktasten werden ebenfalls ausgelassen. Wir behandeln nicht den Fall, dass die Titelleisten und die Titel der Andockfenster zu klein für ihren Inhalt werden, sondern ziehen einfach Untersteuerungen übereinander.

Wir haben nicht versucht, die Java-Schriftarten zu emulieren. Java und Qt verwenden sehr unterschiedliche Font-Engines, so dass wir den Aufwand nicht für lohnenswert halten, da wir den Stil nur als Beispiel für diese Übersicht verwenden.

Wir haben die Farben für die linearen Farbverläufe, die z. B. für Schaltflächen, Symbolleisten und Kontrollkästchen verwendet werden, hart kodiert (wir verwenden nicht die QPalette). Der Grund dafür ist, dass die Java-Palette diese Farben nicht erzeugen kann. Java ändert diese Farben ohnehin nicht in Abhängigkeit von der Widget-Farbgruppe oder -Rolle (sie sind nicht von der Palette abhängig), so dass dies in jedem Fall kein Problem darstellt.

Es sind die Widgets von Qt, die gestylt werden. Einige Widgets gibt es in Java überhaupt nicht, z.B. QToolBox. Andere enthalten Elemente, die die Java-Widgets nicht haben. Das Baum-Widget ist ein Beispiel für letzteres, da der JTree in Java keine Kopfzeile hat.

Der Stil behandelt keine umgekehrten Layouts. Wir gehen davon aus, dass die Layoutrichtung von links nach rechts ist. QCommonStyle behandelt umgekehrte Widgets; wenn wir umgekehrte Layouts implementieren würden, müssten Widgets, die wir die Position von Unterelementen ändern oder die Textausrichtung in Beschriftungen selbst handhaben, aktualisiert werden.

Gestalten von Java-Kontrollkästchen

Als Beispiel wollen wir die Gestaltung von Kontrollkästchen im Java-Stil untersuchen. Wir beschreiben den gesamten Prozess und drucken den gesamten Code sowohl im Java-Stil als auch in den beteiligten Qt-Klassen. Im weiteren Verlauf dieses Dokuments werden wir den Quellcode der einzelnen Widgets nicht mehr untersuchen. Dies gibt Ihnen hoffentlich eine Idee, wie Sie den Code durchsuchen können, wenn Sie bestimmte Implementierungsdetails überprüfen müssen; die meisten Widgets folgen der gleichen Struktur wie die Kontrollkästchen. Wir haben den Code von QCommonStyle etwas bearbeitet, um Code zu entfernen, der für die Gestaltung von Kontrollkästchen nicht direkt relevant ist.

Wir beginnen mit einem Blick darauf, wie QCheckBox seine Stiloption aufbaut, die QStyleOptionButton für Kontrollkästchen ist:

    opt.initFrom(q);
        if (down)
        opt.state |= QStyle::State_Sunken;
    if (tristate && noChange)
        opt.state |= QStyle::State_NoChange;
    else
        opt.state |= checked ? QStyle::State_On :
        QStyle::State_Off;
    if (q->testAttribute(Qt::WA_Hover) &&  q->underMouse()) {
        if (hovering)
        opt.state |= QStyle::State_MouseOver;
        else
        opt.state &= ~QStyle::State_MouseOver;
    }
    opt.text = text;
    opt.icon = icon;
    opt.iconSize = q->iconSize();

Zuerst lassen wir QStyleOption die Option mit den Informationen einrichten, die für alle Widgets mit initFrom() gemeinsam sind. Wir werden uns dies in Kürze ansehen.

QStyleOptionDie Variable down ist true, wenn der Benutzer das Kästchen nach unten drückt; dies gilt für das Kontrollkästchen unabhängig davon, ob es markiert ist oder nicht. Der Status State_NoChange wird gesetzt, wenn wir ein Kontrollkästchen mit drei Zuständen haben und es teilweise markiert ist. Es hat den Status State_On, wenn das Kästchen angekreuzt ist, und State_Off, wenn es nicht angekreuzt ist. State_MouseOver wird gesetzt, wenn die Maus über das Kästchen bewegt wird und das Widget das Attribut Qt::WA_Hover gesetzt hat - Sie setzen dies in QStyle::polish(). Darüber hinaus enthält die Stiloption auch den Text, das Symbol und die Symbolgröße der Schaltfläche.

initFrom() richtet die Stiloption mit den Attributen ein, die für alle Widgets gleich sind. Wir drucken hier seine Implementierung:

    state = QStyle::State_None;
    if (widget->isEnabled())
        state |= QStyle::State_Enabled;
    if (widget->hasFocus())
        state |= QStyle::State_HasFocus;
    if (widget->window()->testAttribute(Qt::WA_KeyboardFocusChange))
        state |= QStyle::State_KeyboardFocusChange;
    if (widget->underMouse())
        state |= QStyle::State_MouseOver;
    if (widget->window()->isActiveWindow())
        state |= QStyle::State_Active;
#ifdef QT_KEYPAD_NAVIGATION
    if (widget->hasEditFocus())
        state |= QStyle::State_HasEditFocus;
#endif

    direction = widget->layoutDirection();
    rect = widget->rect();
    palette = widget->palette();
    fontMetrics = widget->fontMetrics();

Die Option State_Enabled wird gesetzt, wenn das Widget aktiviert ist. Wenn das Widget den Fokus hat, wird das State_HasFocus Flag gesetzt. Ebenso wird das State_Active Flag gesetzt, wenn das Widget ein Kind des aktiven Fensters ist. State_MouseOver wird nur gesetzt, wenn für das Widget das Flag WA_HoverEnabled windows gesetzt ist. Beachten Sie, dass die Tastaturnavigation in Qt aktiviert sein muss, damit das State_HasEditFocus enthalten ist; es ist nicht standardmäßig enthalten.

Zusätzlich zum Setzen von Statusflags enthält QStyleOption weitere Informationen über das Widget: direction ist die Layoutrichtung des Layouts, rect ist das Begrenzungsrechteck des Widgets (der Bereich, in dem gezeichnet werden soll), palette ist die QPalette, die zum Zeichnen des Widgets verwendet werden soll, und fontMetrics ist die Metrik der Schriftart, die vom Widget verwendet wird.

Wir geben ein Bild eines Kontrollkästchens und die dazu passende Stiloption an.

A Java style checkbox

Das obige Kontrollkästchen hat die folgenden Statusflags in seiner Stiloption:

Status-Flagsetzen
State_SunkenJa
State_NoChangeNein
State_OnJa
State_OffNein
State_MouseOverJa
State_EnabledJa
State_HasFocusJa
State_KeyboardFocusChangeNein
State_ActiveJa

Die QCheckBox malt sich in QWidget::paintEvent() mit der Stiloption opt und QStylePainter p . Die Klasse QStylePainter ist eine Komfortklasse zum Zeichnen von Stilelementen. Vor allem umhüllt sie die Methoden in QStyle, die zum Malen verwendet werden. Die Klasse QCheckBox zeichnet sich selbst wie folgt:

    QStylePainter p(this);
    QStyleOptionButton opt = d->getStyleOption();
    p.drawControl(QStyle::CE_CheckBox, opt);

QCommonStyle Sie behandelt das CE_CheckBox-Element. Das QCheckBox hat zwei Unterelemente: SE_CheckBoxIndicator (der Indikator für das Häkchen) und SE_CheckBoxContents (der Inhalt, der für die Beschriftung der Checkbox verwendet wird). QCommonStyle implementiert auch die Begrenzungsrechtecke dieser Unterelemente. Als nächstes sehen wir uns den Code von QCommonStyle an:

    QStyleOptionButton subopt = *btn;
    subopt.rect = subElementRect(SE_CheckBoxIndicator, btn, widget);
    drawPrimitive(PE_IndicatorCheckBox, &subopt, p, widget);
    subopt.rect = subElementRect(SE_CheckBoxContents, btn, widget);
    drawControl(CE_CheckBoxLabel, &subopt, p, widget);

    if (btn->state & State_HasFocus) {
        QStyleOptionFocusRect fropt;
        fropt.QStyleOption::operator=(*btn);
        fropt.rect = subElementRect(SE_CheckBoxFocusRect, btn, widget);
        drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
    }

Wie aus dem Codeauszug ersichtlich ist, holt sich der Common Style die Bounding Rectangles der beiden Unterelemente von CE_CheckBox und zeichnet sie dann. Wenn das Kontrollkästchen den Fokus hat, wird auch der Fokusrahmen gezeichnet.

Der Java-Stil zeichnet CE_CheckBoxIndicator, während QCommonStyle sich um CE_CheckboxLabel kümmert. Wir werden jede Implementierung untersuchen und mit CE_CheckBoxLabel beginnen:

    const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt);
    uint alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter);

    if (!styleHint(SH_UnderlineShortcut, btn, widget))
        alignment |= Qt::TextHideMnemonic;
    QPixmap pix;
    QRect textRect = btn->rect;
    if (!btn->icon.isNull()) {
        pix = btn->icon.pixmap(btn->iconSize, btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled);
        drawItemPixmap(p, btn->rect, alignment, pix);
        if (btn->direction == Qt::RightToLeft)
            textRect.setRight(textRect.right() - btn->iconSize.width() - 4);
        else
            textRect.setLeft(textRect.left() + btn->iconSize.width() + 4);
    }
    if (!btn->text.isEmpty()){
        drawItemText(p, textRect, alignment | Qt::TextShowMnemonic,
            btn->palette, btn->state & State_Enabled, btn->text, QPalette::WindowText);
    }

visualAlignment() passt die Ausrichtung des Textes entsprechend der Layoutrichtung an. Dann wird ein Icon gezeichnet, falls es existiert, und der Platz für den Text angepasst. drawItemText() zeichnet den Text unter Berücksichtigung der Ausrichtung, der Layoutrichtung und des Mnemonics. Es verwendet auch die Palette, um den Text in der richtigen Farbe zu zeichnen.

Das Zeichnen von Beschriftungen ist oft etwas kompliziert. Glücklicherweise kann dies normalerweise von der Basisklasse erledigt werden. Der Java-Stil implementiert seine eigene Beschriftung für Drucktasten, da Java den Inhalt von Schaltflächen auch dann zentriert, wenn die Schaltfläche ein Symbol hat. Sie können sich diese Implementierung ansehen, wenn Sie ein Beispiel für die Neuimplementierung des Zeichnens von Etiketten benötigen.

Schauen wir uns nun die Java-Implementierung von CE_CheckBoxIndicator in drawControl() an:

        case PE_IndicatorCheckBox: {
            painter->save();
            drawButtonBackground(option, painter, true);

            if (option->state & State_Enabled &&
                option->state & State_MouseOver &&
                !(option->state & State_Sunken)) {
                painter->setPen(option->palette.color(QPalette::Button));
                QRect rect = option->rect.adjusted(1, 1, -2, -2);
                painter->drawRect(rect);
                rect = rect.adjusted(1, 1, -1, -1);
                painter->drawRect(rect);
            }

            if (option->state & State_On) {
                QImage image(":/images/checkboxchecked.png");
                painter->drawImage(option->rect.topLeft(), image);
            }
            painter->restore();
            break;

Zuerst speichern wir den Zustand des Painters. Das ist nicht immer notwendig, aber in diesem Fall braucht QCommonStyle den Painter in dem Zustand, in dem er sich beim Aufruf von PE_IndicatorCheckBox befand (wir könnten den Zustand natürlich auch mit Funktionsaufrufen setzen). Dann verwenden wir drawButtonBackground(), um den Hintergrund des Checkbox-Indikators zu zeichnen. Dies ist eine Hilfsfunktion, die den Hintergrund und auch den Rahmen von Drucktasten und Kontrollkästchen zeichnet. Wir sehen uns diese Funktion weiter unten an. Dann prüfen wir, ob die Maus über dem Kontrollkästchen schwebt. Wenn ja, zeichnen wir den Rahmen, den Java-Kontrollkästchen haben, wenn das Kästchen nicht gedrückt ist und sich die Maus darüber befindet. Sie werden feststellen, dass Java keine dreistufigen Kontrollkästchen handhabt, daher haben wir dies nicht implementiert.

Hier verwenden wir ein PNG-Bild für unseren Indikator. Wir könnten auch prüfen, ob das Widget deaktiviert ist. Dann müssten wir ein anderes Bild mit dem Indikator in der deaktivierten Farbe verwenden.

void JavaStyle::drawButtonBackground(const QStyleOption *option,
                                     QPainter *painter, bool isCheckbox) const
{
    QBrush buttonBrush = option->palette.button();
    bool sunken = option->state & State_Sunken;
    bool disabled = !(option->state & State_Enabled);
    bool on = option->state & State_On;

    if (!sunken && !disabled && (!on || isCheckbox))
        buttonBrush = gradientBrush(option->rect);

        painter->fillRect(option->rect, buttonBrush);

        QRect rect = option->rect.adjusted(0, 0, -1, -1);

        if (disabled)
            painter->setPen(option->palette.color(QPalette::Disabled,
                                                  QPalette::WindowText));
        else
            painter->setPen(option->palette.color(QPalette::Mid));

        painter->drawRect(rect);

        if (sunken && !disabled) {
            drawSunkenButtonShadow(painter, rect,
                   option->palette.color(QPalette::Mid),
                   option->direction == Qt::RightToLeft);
    }
}

Wir haben gesehen, wie Kontrollkästchen im Java-Stil gestylt werden, und zwar von dem Zeitpunkt, an dem das Widget eine Malanforderung erhält, bis zu dem Zeitpunkt, an dem der Stil fertig gezeichnet ist. Um im Detail zu erfahren, wie jedes Widget gezeichnet wird, müssen Sie den Code Schritt für Schritt durchgehen, wie wir es hier getan haben. In der Regel reicht es jedoch aus, zu wissen, welche Stilelemente die Widgets zeichnen. Das Widget baut eine Stiloption auf und ruft den Stil ein oder mehrere Male auf, um die Stilelemente zu zeichnen, aus denen es besteht. Normalerweise reicht es auch aus, die Zustände, in denen sich ein Widget befinden kann, und die anderen Inhalte der Stiloption zu kennen, d. h. das, was wir im nächsten Abschnitt auflisten.

Widget-Walkthrough

In diesem Abschnitt werden wir untersuchen, wie die meisten Widgets von Qt gestylt werden. Wir hoffen, dass dies Ihnen etwas Zeit und Mühe bei der Entwicklung Ihrer eigenen Stile und Widgets erspart. Sie werden hier keine Informationen finden, die Sie nicht auch anderswo finden können (z.B. durch Untersuchung des Quellcodes oder der Klassenbeschreibungen für die stilbezogenen Klassen).

Wir verwenden hauptsächlich Java-Stil-Widgets als Beispiele. Der Java-Stil zeichnet nicht jedes Element in den Elementbäumen. Das liegt daran, dass sie für dieses Widget im Java-Stil nicht sichtbar sind. Wir stellen dennoch sicher, dass alle Elemente in einer Weise implementiert sind, die dem Java-Stil entspricht, da benutzerdefinierte Widgets sie benötigen könnten (dies schließt jedoch nicht aus, dass wir die Implementierungen QCommonStyle überlassen).

Für jedes Widget wird folgendes angegeben:

  • Eine Tabelle mit den Elementen (Variablen usw.) seiner Stiloption.
  • Eine Tabelle mit den Zustandsflags (QStyle::StateFlag), die für das Widget gesetzt werden können und wann die Zustände gesetzt sind.
  • Sein Elementbaum (siehe Abschnitt Die Stilelemente).
  • Ein Bild des Widgets, in dem die Elemente skizziert sind.

Der Elementbaum enthält die primitiven, Kontroll- und komplexen Stilelemente. Wenn Sie den Elementbaum von oben nach unten durchlaufen, erhalten Sie die Reihenfolge, in der die Elemente gezeichnet werden sollen. In den Knoten haben wir die Rechtecke der Unterelemente, die Untersteuerelemente und die Pixelmetriken geschrieben, die beim Zeichnen des Elements des Knotens berücksichtigt werden sollten.

Unser Ansatz für das Styling konzentriert sich auf das Zeichnen der Widgets. Die Berechnungen der Rechtecke der Unterelemente, der Untersteuerelemente und der Pixelmetriken, die beim Zeichnen verwendet werden, werden nur als Inhalte in den Elementbäumen aufgeführt. Beachten Sie, dass es Rechtecke und Pixelmetriken gibt, die nur von Widgets verwendet werden. Dadurch bleiben diese Berechnungen in der exemplarischen Vorgehensweise unbehandelt. Zum Beispiel rufen die Funktionen subControlRect() und sizeFromContents() oft subElementRect() auf, um ihre begrenzenden Rechtecke zu berechnen. Wir könnten dafür auch Bäume zeichnen. Wie diese Berechnungen durchgeführt werden, bleibt jedoch den einzelnen Stilen überlassen, und sie müssen keiner bestimmten Struktur folgen (Qt schreibt keine bestimmte Struktur vor). Sie sollten aber trotzdem darauf achten, dass Sie die entsprechenden Pixelmetriken verwenden. Um den Umfang des Dokuments zu begrenzen, haben wir uns daher entschieden, keine Bäume einzufügen oder die Berechnungen des Java-Stils (oder eines anderen) zu beschreiben.

Vielleicht sind Sie verwirrt, wie die verschiedenen Pixelmetriken, Unterelementrechtecke und Untersteuerungsrechtecke bei der Untersuchung der Bäume zu verwenden sind. Wenn Sie nach dem Lesen der QStyle enum-Beschreibungen noch Zweifel haben, empfehlen wir Ihnen, die QCommonStyle -Implementierung zu prüfen.

Einige der Begrenzungsrechtecke, die wir in den Widget-Bildern skizzieren, sind gleich. Der Grund dafür ist, dass einige Elemente Hintergründe zeichnen, während andere Rahmen und Beschriftungen zeichnen. Im Zweifelsfall sollten Sie die Beschreibung der einzelnen Elemente auf QStyle überprüfen. Außerdem sind einige Elemente dazu da, das Layout zu gestalten, d. h. zu entscheiden, wo andere Elemente gezeichnet werden sollen.

Gemeinsame Widget-Eigenschaften

Einige Zustände und Variablen sind für alle Widgets gleich. Diese werden mit QStyleOption::initFrom() gesetzt. Nicht alle Elemente verwenden diese Funktion; es sind die Widgets, die die Stiloptionen erstellen, und für einige Elemente sind die Informationen von initFrom() nicht notwendig.

Es folgt eine Tabelle mit den allgemeinen Zuständen:

ZustandZustand Setzen wenn
State_EnabledWird gesetzt, wenn das Widget nicht deaktiviert ist (siehe QWidget::setEnabled())
State_FocusWird gesetzt, wenn das Widget den Fokus hat (siehe QWidget::hasFocus())
State_KeyboardFocusChangeWird gesetzt, wenn der Benutzer den Fokus mit der Tastatur ändert (siehe Qt::WA_KeyboardFocusChange)
State_MouseOverWird gesetzt, wenn sich der Mauszeiger über dem Widget befindet.
State_ActiveWird gesetzt, wenn das Widget ein Kind des aktiven Fensters ist.
State_HasEditFocusSetzen, wenn das Widget den Bearbeitungsfokus hat

Die anderen üblichen Mitglieder für Widgets sind:

MitgliedInhalt
rectDas Begrenzungsrechteck des zu zeichnenden Elements. Dieses wird auf das Begrenzungsrechteck des Widgets gesetzt (QWidget::rect()).
RichtungDie Layout-Richtung; ein Wert des Qt::LayoutDirection enum.
paletteDie QPalette, die beim Zeichnen des Elements verwendet wird. Dies wird auf die Palette des Widgets gesetzt (QWidget::palette()).
fontMetricsDie QFontMetrics, die beim Zeichnen von Text auf dem Widget verwendet werden soll.

Die komplexen Stiloptionen (Klassen, die QStyleOptionComplex erben), die für komplexe Stilelemente verwendet werden, teilen sich zwei Variablen: subControls und activeSubControls. Beide Variablen sind eine ODER-Verknüpfung von QStyle::SubControl enum-Werten. Sie geben an, aus welchen Untersteuerelementen das komplexe Steuerelement besteht und welche dieser Steuerelemente gerade aktiv sind.

Wie bereits erwähnt, berechnet der Stil die Größe des Widget-Inhalts, woraus die Widgets ihre Größenhinweise berechnen. Darüber hinaus verwenden komplexe Steuerelemente den Stil auch, um zu prüfen, über welchen Untersteuerelementen sich die Maus befindet.

Widget-Referenz

Ohne weitere Verzögerung präsentieren wir Ihnen eine Übersicht über die Widgets; jedes Widget hat seinen eigenen Unterabschnitt.

Drucktasten

Die Stilstruktur für Drucktasten ist unten dargestellt. Wenn Sie den Baum von oben nach unten durchlaufen, erhalten Sie die Reihenfolge, in der die Elemente gezeichnet werden sollen.

The style structure for push buttons

Die Anordnung der Schaltflächen in Bezug auf die Elementgrenzen variiert von Stil zu Stil. Das macht es schwierig, konzeptionelle Bilder davon zu zeigen. Außerdem können Elemente die gleichen Grenzen haben - oder sollen sogar dieselben haben; PE_PushButtonBevel wird zum Beispiel in QCommonStyle verwendet, um die darin enthaltenen Elemente zu zeichnen: PE_FrameDefaultButton, PE_FrameButtonBevel und PE_PanelButtonCommand, die alle dieselben Grenzen im gemeinsamen Stil haben. PE_PushButtonBevel ist auch für das Zeichnen der Menüanzeige verantwortlich (QCommonStyle zeichnet PE_IndicatorArrowDown).

Nachfolgend sehen Sie ein Bild einer Drucktaste im Java-Stil, das die Begrenzungsrechtecke der Elemente zeigt. Die Farben werden verwendet, um die Begrenzungsrechtecke im Bild zu trennen; sie erfüllen keinen anderen Zweck. Dies gilt auch für ähnliche Bilder für die anderen Widgets.

Der Java-Stil, wie auch alle anderen in Qt implementierten Stile, verwendet PE_FrameButtonBevel nicht. Es ist üblich, dass eine Schaltfläche mit einem PE_DefaultFrame das Rechteck des PE_PanelButtonCommand um PM_ButtonDefaultIndicator anpasst. Das CE_PushButtonLabel wird durch Anpassung des Rects um PM_DefaultFrameWidth gefunden.

Wir werden nun die Stiloption für Drucktasten untersuchen - QStyleOptionButton. Es folgt eine Tabelle für die Zustände, die QPushButton mit der Stiloption einstellen kann:

ZustandEingestellter Zustand Wenn
State_SunkenDie Taste ist gedrückt oder das Menü wird angezeigt
State_OnTaste ist markiert
State_RaisedDie Schaltfläche ist nicht flach und nicht gedrückt

Andere Mitglieder von QStyleOptionButton sind:

MitgliedInhalt
EigenschaftenFlags des QStyleOptionButton::ButtonFeatures enum, das verschiedene Button-Eigenschaften beschreibt (siehe enum)
SymbolDie Schaltfläche QIcon (falls vorhanden)
iconSizeDie QSize des Symbols
textein QString mit dem Text der Schaltflächen

Check- und Radio-Buttons

Die Strukturen für Radio- und Checkbuttons sind identisch. Wir zeigen die Struktur mit QCheckBox Element- und Pixelmetriknamen:

QStyleOptionButton Sowohl für Check- als auch für Radio-Buttons wird die Option style verwendet. Zunächst geben wir eine Tabelle der Zustände an, die in der Option eingestellt werden können:

ZustandStatus Eingestellt wenn
State_sunkenDas Kästchen ist gedrückt
State_NoChangeDas Kästchen ist teilweise markiert (bei Kontrollkästchen mit drei Zuständen).
State_OnDas Kästchen ist markiert
State_OffDas Kästchen ist nicht angekreuzt

Siehe Push Buttons für eine Tabelle über andere Mitglieder der Klasse QStyleOptionButton.

Registerkarten

In Qt verwendet QTabBar den Stil zum Zeichnen der Tabs. Tabs existieren entweder in einer QTabWidget, die eine QTabBar enthält, oder als separate Leiste. Wenn die Leiste nicht Teil eines Tab-Widgets ist, zeichnet sie ihre eigene Basis.

QTabBar legt die Registerkarten aus, so dass der Stil keine Kontrolle über die Platzierung der Registerkarten hat. Beim Anlegen der Registerkarten bittet die Leiste den Stil jedoch um PM_TabBarTabHSpace und PM_TabBarTabVSpace, d. h. um zusätzliche Breite und Höhe über der Mindestgröße der Registerkartenbeschriftung (Symbol und Text). Die Formatvorlage kann auch die Größe der Registerkarten beeinflussen, bevor diese angelegt werden, da die Registerkartenleiste CT_TabBarTab anfordert. Das Begrenzungsrechteck der Leiste wird vom Registerkarten-Widget festgelegt, wenn es Teil des Widgets ist (noch unter Berücksichtigung von CT_TabBarTab).

Die Registerkartenleiste ist für das Zeichnen der Schaltflächen verantwortlich, die auf der Registerkartenleiste erscheinen, wenn nicht alle Registerkarten passen. Ihre Platzierung wird nicht durch die Formatvorlage gesteuert, aber die Schaltflächen sind QToolButtonund werden daher durch die Formatvorlage gezeichnet.

Hier ist die Formatvorlagenstruktur für QTabWidget und QTabBar:

Die gestrichelten Linien zeigen an, dass QTabWidget eine Registerkartenleiste enthält, aber nicht die Registerkartenleiste selbst zeichnet. QTabBar zeichnet nur seine Grundlinie, wenn es nicht Teil eines Registerkarten-Widgets ist, und es enthält zwei Werkzeugschaltflächen, die die Leiste verschieben, wenn nicht alle Registerkarten passen; siehe Werkzeugschaltflächen für ihren Elementbaum. Beachten Sie auch, dass die Schaltflächen Kinder der Registerkartenleiste sind und daher nach der Leiste gezeichnet werden. Die Begrenzungsrechtecke der Registerkarten überlappen die Basis um PM_TabBarBaseOverlap.

Hier sehen Sie ein Registerkarten-Widget im Java-Stil:

Im Java-Stil haben die Form der Registerkartenleiste und die Beschriftung das gleiche Begrenzungsrechteck wie CE_TabBarTab. Beachten Sie, dass sich die Registerkarten mit dem Rahmen des Registerkarten-Widgets überlappen. Die Basis der Registerkartenleiste (falls gezeichnet) ist der Bereich, in dem sich die Registerkarten und der Rahmen überlappen.

Die Stiloption für Tabulatoren (QStyleOptionTab) enthält die notwendigen Informationen zum Zeichnen von Tabulatoren. Die Option enthält die Position der Registerkarte in der Registerkartenleiste, die Position der ausgewählten Registerkarte, die Form der Registerkarte, den Text, das Symbol und die Größe des Symbols.

Da sich die Registerkarten im Java-Stil nicht überschneiden, zeigen wir auch ein Bild eines Registerkarten-Widgets im allgemeinen Stil. Wenn Sie möchten, dass sich die Registerkarten horizontal überlappen, müssen Sie das beim Zeichnen der Registerkarten in CE_TabBarTabShape tun. Die Begrenzungsrechtecke der Registerkarten werden durch die Registerkartenleiste nicht verändert. Die Registerkarten werden von links nach rechts in Form einer nördlichen Registerkartenleiste gezeichnet, von oben nach unten in Form einer östlichen Registerkartenleiste, usw. Die ausgewählte Registerkarte wird zuletzt gezeichnet, so dass es einfach ist, sie über die anderen Registerkarten zu ziehen (wenn sie größer sein soll).

Es folgt eine Tabelle mit den Zuständen, die eine Registerkartenleiste für ihre Registerkarten festlegen kann:

ZustandStatus gesetzt wenn
State_SunkenDie Registerkarte wird mit der Maus angeklickt.
State_SelectedWenn es die aktuelle Registerkarte ist.
State_HasFocusDie Registerkartenleiste hat den Fokus und die Registerkarte ist ausgewählt.

Beachten Sie, dass einzelne Registerkarten auch dann deaktiviert sein können, wenn die Registerkartenleiste nicht aktiviert ist. Die Registerkarte ist aktiv, wenn die Registerkartenleiste aktiv ist.

Es folgt eine Tabelle der Mitglieder von QStyleOptionTab:

MitgliedInhalt
cornerWidgetsFlags des CornerWidget-Enums, die angeben, ob und welche Eckwidgets die Registerkartenleiste hat.
SymbolDie QIcon der Registerkarte.
iconGrößeDie QSize des Icons.
PositionEin TabPosition-Enum-Wert, der die Position der Registerkarte auf der Leiste im Verhältnis zu den anderen Registerkarten angibt.
rowGibt an, in welcher Zeile sich die Registerkarte befindet.
selectedPositionEin Wert der Aufzählung SelectedPosition, der angibt, ob die ausgewählte Registerkarte an die Registerkarte angrenzt oder diese selbst ist.
FormEin Wert der Aufzählung QTabBar::Shape, der angibt, ob die Registerkarte abgerundete oder dreieckige Ecken hat, sowie die Ausrichtung der Registerkarte.
textDer Text der Registerkarte.

Der Rahmen für Registerkarten-Widgets verwendet QStyleOptionTabWidgetFrame als Stiloption. Wir listen hier seine Mitglieder auf. Neben den allgemeinen Flags hat er keine gesetzten Zustände.

MitgliedInhalt
leftCornerWidgetSizeDie QSize des Widgets der linken Ecke (falls vorhanden).
rightCornerWidgetSizeDie QSize des Widgets der rechten Ecke (falls vorhanden).
lineWidthEnthält die Linienbreite für das Zeichnen des Panels.
midLineWithDieser Wert ist derzeit immer 0.
formDie Form der Registerkarten in der Registerkartenleiste.
tabBarSizeDie QSize der Registerkartenleiste.

Bildlaufleisten

Hier ist die Stilstruktur für Bildlaufleisten:

QScrollBar erstellt einfach seine Stiloption und zeichnet dann CC_ScrollBar. Einige Stile zeichnen den Hintergrund von add page und sub page mit PE_PanelButtonBevel und verwenden auch Indikatorpfeile, um die Pfeile in den Indikatoren für die nächste und vorherige Zeile zu zeichnen; wir haben diese nicht in den Baum aufgenommen, da ihre Verwendung dem individuellen Stil überlassen bleibt. Die Stilvorlage PM_MaximumDragDistance ist die maximale Entfernung in Pixeln, die die Maus von den Grenzen der Bildlaufleiste entfernen kann, ohne den Griff zu verschieben.

Hier sehen Sie ein Bild einer Bildlaufleiste im Java-Stil:

Sie werden feststellen, dass sich die Bildlaufleiste etwas von der in Java unterscheidet, da sie zwei Zeilenanzeiger hat. Wir haben dies getan, um zu zeigen, dass Sie zwei separate Begrenzungsrechtecke für ein einziges Untersteuerelement haben können. Die Bildlaufleiste ist ein Beispiel für ein Widget, das vollständig durch den Java-Stil implementiert ist - QCommonStyle ist nicht an der Zeichnung beteiligt.

Schauen wir uns die verschiedenen Zustände an, die eine Bildlaufleiste in der Stiloption annehmen kann:

ZustandStatus gesetzt wenn
State_HorizontalDie Bildlaufleiste ist horizontal.

Die Stiloption von QScrollBar ist QStyleOptionSlider. Ihre Elemente sind in der folgenden Tabelle aufgeführt. Die Option wird von allen QAbstractSliders verwendet; wir beschreiben hier nur die für Bildlaufleisten relevanten Mitglieder.

MitgliedInhalt
maximalDer maximale Wert der Bildlaufleiste.
minimalDer Mindestwert der Bildlaufleiste.
notchTargetDie Anzahl der Pixel zwischen den Einkerbungen.
AusrichtungEin Wert des Qt::Orientation enum, der angibt, ob die Bildlaufleiste vertikal oder horizontal ist.
pageStepDie Zahl, um die der Wert des Schiebereglers (relativ zur Größe des Schiebereglers und seines Wertebereichs) in Seitenschritten erhöht oder verringert werden soll.
singleStepDie Zahl, um die der Wert des Schiebereglers in Einzelschritten (oder Zeilenschritten) erhöht oder verringert werden soll.
sliderValueDer Wert des Schiebereglers.
sliderPositionDie Position des Schiebereglergriffs. Dies ist dasselbe wie sliderValue, wenn die Bildlaufleiste QAbstractSlider::tracking ist. Andernfalls aktualisiert die Bildlaufleiste ihren Wert nicht, bevor die Maus den Griff loslässt.
upsideDownHält die Richtung fest, in der die Bildlaufleiste ihren Wert erhöht. Dies wird anstelle von QStyleOption::direction für alle abstrakten Schieberegler verwendet.

Schieberegler

Bei der Berechnung des Größenhinweises des Schiebereglers werden PM_SliderThickness und PM_SliderLength aus dem Stil abgefragt. Wie bei den Bildlaufleisten lässt QSlider den Benutzer den Griff nur dann bewegen, wenn sich die Maus innerhalb PM_MaximumDragDistance der Schiebereglerbegrenzungen befindet. Wenn er sich selbst zeichnet, erstellt er die Stiloption und ruft drawComplexControl() mit CC_Slider auf:

Wir zeigen auch ein Bild eines Schiebereglers im Java-Stil. Wir zeigen die Begrenzungsrechtecke der Unterelemente, da alle Zeichnungen in CC_Slider vorgenommen werden.

QSlider verwendet QStyleOptionSlider wie alle QAbstractSliders. Wir zeigen eine Tabelle mit den Mitgliedern, die QSlider beeinflussen:

MitgliedInhalt
MaximumDer maximale Wert des Schiebereglers.
MinimumDer Mindestwert des Schiebereglers.
notchTargetDies ist die Anzahl der Pixel zwischen den einzelnen Kerben.
AusrichtungEin Qt::Orientation enum-Wert, der angibt, ob der Schieberegler vertikal oder horizontal ist.
pageStepDie Zahl, um die der Wert des Schiebereglers in Seitenschritten erhöht oder verringert werden soll.
singleStepDie Zahl, um die der Wert des Schiebereglers in Einzelschritten (oder Zeilenschritten) erhöht oder verringert werden soll.
sliderValueDer Wert des Schiebereglers.
SchiebereglerPositionDie Position des Schiebereglers, die als Schiebereglerwert angegeben wird. Dieser Wert entspricht sliderValue, wenn der Schieberegler tracking ist; andernfalls ändert sich der Wert des Schiebereglers nicht, bis der Griff mit der Maus losgelassen wird.
upsideDownDieses Element wird anstelle von QStyleOption::direction für alle abstrakten Schieberegler verwendet.

Beachten Sie, dass der Schieberegler bei umgekehrten Layouts nicht die Richtung verwendet, sondern upsideDown.

Spin-Boxen

Wenn QSpinBox sich selbst malt, erstellt es ein QStyleOptionSpinBox und fordert den Stil auf, CC_SpinBox zu zeichnen. Das Bearbeitungsfeld ist eine Bearbeitungszeile, die ein Kind der Spin-Box ist. Die Abmessungen des Feldes werden von der Formatvorlage mit SC_SpinBoxEditField berechnet.

Es folgt der Stilbaum für Spinnboxen. Es ist nicht erforderlich, dass ein Stil das Primitiv der Schalttafel verwendet, um die Hintergründe der Indikatoren zu malen. Unterhalb des Baums sehen Sie ein Bild, das die Unterelemente in QSpinBox im Java-Stil zeigt.

QStyleOptionSpinBox ist die Stiloption für Drehkästen. Sie kann die folgenden Zustände für das Drehfeld festlegen:

ZustandStatus gesetzt wenn
State_SunkenWird gesetzt, wenn eines der Unterelemente CC_SpinUp oder CC_SpinDown mit der Maus angeklickt wird.

Die übrigen Mitglieder der Stiloptionen für Spinboxen sind:

EigenschaftFunktion
RahmenBoolescher Wert, der true ist, wenn der Spinnkasten einen Rahmen zeichnen soll.
buttonSymbolsWert des Enums ButtonSymbols, der das Symbol für die Auf-/Ab-Schaltflächen bestimmt.
stepEnabledEin Wert der Aufzählung StepEnabled, der angibt, welche der Schaltflächen des Drehkastens gedrückt sind.

Titelleiste

Das komplexe Steuerelement für die Titelleiste, CC_TitleBar, wird zum Zeichnen der Titelleisten interner Fenster in QMdiArea verwendet. Es besteht normalerweise aus einem Fenstertitel sowie Schaltflächen zum Schließen, Minimieren, Systemmenü und Maximieren. Einige Stile bieten auch Schaltflächen zum Schattieren des Fensters sowie eine Schaltfläche für die kontextsensitive Hilfe.

Die Leiste wird in CC_TitleBar ohne Verwendung von Unterelementen gezeichnet. Wie die einzelnen Stile ihre Schaltflächen zeichnen, bleibt ihnen überlassen, aber es gibt Standard-Pixmaps für die Schaltflächen, die der Stil bereitstellen sollte.

In einem Bild über einer Titelleiste im Java-Stil zeigen wir die Begrenzungsrechtecke der vom Java-Stil unterstützten Unterelemente (die alle mit Standard-Pixmaps gezeichnet werden). Es ist üblich, die Schaltflächenhintergründe mit PE_PanelButtonTool zu zeichnen, aber nicht zwingend erforderlich.

Die Stiloption für Titelleisten ist QStyleOptionTitleBar. Ihre Mitglieder sind:

MitgliedInhalt
SymbolDas Symbol der Titelleiste.
TextDer Text für die Beschriftung der Titelleiste.
windowFlagsFlaggen der Qt::WindowFlag Aufzählung. Die Fenster-Flags, die von QMdiArea für die Fensterverwaltung verwendet werden.
titleBarStateDies ist die QWidget::windowState() des Fensters, das die Titelleiste enthält.

Kombinationsfeld

Ein QComboBox verwendet den Stil, um die Schaltfläche und die Beschriftung von nicht editierbaren Feldern mit CC_ComboBox und CE_ComboBoxLabel zu zeichnen.

Die Liste, die angezeigt wird, wenn der Benutzer auf das Kombinationsfeld klickt, wird von einem Delegaten gezeichnet, auf den wir in dieser Übersicht nicht eingehen. Sie können jedoch den Stil verwenden, um die Größe und Position der Liste mit dem Unterelement SC_ComboBoxListBoxPopup zu steuern. Der Stil bestimmt auch, wo das Bearbeitungsfeld für editierbare Felder mit SC_ComboBoxEditField platziert werden soll; das Feld selbst ist ein QLineEdit, das ein Kind des Kombinationsfeldes ist.

Wir zeigen ein Bild über ein Java-Kombinationsfeld, in dem wir seine Unterelemente und Unterelementrechtecke skizziert haben:

Java-Kombinationsfelder verwenden das Fokus-Rect nicht; es ändert seine Hintergrundfarbe, wenn es den Fokus hat. Das Feld SC_ComboBoxEdit wird sowohl von QComboBox zur Berechnung der Größe des Eingabefeldes als auch von der Formatvorlage zur Berechnung der Größe der Beschriftung des Kombinationsfeldes verwendet.

Die Stiloption für Kombinationsfelder ist QStyleOptionComboBox. Sie kann die folgenden Zustände festlegen:

StatusSetzen, wenn
State_SelectedDas Feld ist nicht bearbeitbar und hat den Fokus.
State_SunkenSC_ComboBoxArrow ist aktiv.
State_onDer Container (Liste) des Feldes ist sichtbar.

Die Stiloptionen anderer Mitglieder sind:

MitgliedInhalt
aktuellesIconDas Symbol des aktuellen (ausgewählten) Elements der Combobox.
aktuellerTextDer Text des aktuellen Eintrags in der Box.
editierbarGibt an, ob das Kombinationsfeld editierbar ist oder nicht.
RahmenHält fest, ob das Kombinationsfeld einen Rahmen hat oder nicht.
iconSizeDie Größe des Symbols des aktuellen Elements.
popupRectDas Begrenzungsrechteck der Popup-Liste des Kombinationsfeldes.

Gruppenboxen

Bei der Berechnung des Größenhinweises holt sich QGroupBox drei Pixelmetriken aus dem Stil: PM_IndicatorWidth, PM_CheckBoxLabelSpacing, und PM_IndicatorHeight. QGroupBox hat den folgenden Stilelementbaum:

Qt macht keine Einschränkungen, wie das Kontrollkästchen gezeichnet wird; der Java-Stil zeichnet es mit CE_IndicatorCheckBox. Siehe Check und Radio Buttons für den kompletten Baum.

Wir zeigen auch ein Bild des Widgets mit den gezeichneten Untersteuerelementen und Untersteuerungsrechtecken:

Die Stiloption für Gruppenrahmen ist QStyleOptionGroupBox. Die folgenden Zustände können eingestellt werden:

StatusSetzen wenn
State_OnDas Kontrollkästchen ist markiert.
State_SunkenDas Kontrollkästchen ist heruntergedrückt.
State_OffDas Kontrollkästchen ist nicht angekreuzt (oder es gibt kein Kontrollkästchen).

Die übrigen Mitglieder von QStyleOptionGroupBox sind:

MitgliedInhalt
EigenschaftenFlags des QStyleOptionFrame::FrameFeatures enum, die den Rahmen des Gruppenrahmens beschreiben.
lineWidthDie Linienbreite, mit der das Feld gezeichnet werden soll. Dieser Wert ist immer 1.
textDer Text des Gruppenrahmens.
textAusrichtungDie Ausrichtung des Titels des Gruppenrahmens.
textColorDie QColor des Textes.

Aufteiler

Da die Struktur von Splittern einfach ist und keine Unterelemente enthält, werden keine Bilder von Splittern eingefügt. CE_Splitter verwendet keine anderen Elemente oder Metriken.

Für seine Stiloption verwendet der Splitter die Basisklasse QStyleOption. Er kann die folgenden Statusflags setzen:

ZustandSetzen Wenn
State_HorizontalWird gesetzt, wenn es sich um einen horizontalen Splitter handelt.

QSplitter verwendet nicht initFrom(), um seine Option einzurichten; er setzt die Flags State_MouseOver und State_Disabled selbst.

Fortschrittsbalken

Das Element CE_ProgressBar wird von QProgressBar verwendet, und es ist das einzige Element, das von diesem Widget verwendet wird. Wir beginnen mit der Stilstruktur:

Hier ist ein Fortschrittsbalken im allgemeinen Stil (die Begrenzungsrechtecke im Java-Stil sind gleich):

Die Stiloption für QProgressBar ist QStyleOptionProgressBar. Der Balken setzt keine Statusflags, aber die anderen Mitglieder der Option sind:

MitgliedInhalt
MinimumDer Mindestwert des Balkens.
MaximumDer Maximalwert des Balkens.
FortschrittDer aktuelle Wert des Balkens.
textAusrichtungWie der Text in der Beschriftung ausgerichtet ist.
textVisibleOb die Beschriftung gezeichnet wird.
textDer Text des Etiketts.
AusrichtungFortschrittsbalken können vertikal oder horizontal sein.
invertedAppearanceDer Fortschritt ist invertiert (d. h. von rechts nach links in einem horizontalen Balken).
bottomToTopBoolescher Wert, der, falls true, die Beschriftung von vertikalen Fortschrittsbalken um 90 Grad dreht.

Werkzeug-Schaltflächen

Werkzeugschaltflächen existieren entweder unabhängig oder als Teil von Werkzeugleisten. Sie werden in beiden Fällen gleich gezeichnet. Das Widget QToolButton zeichnet nur ein Stilelement: CC_ToolButton.

Unten sehen Sie eine Baumstruktur der Stilstruktur des Widgets:

Beachten Sie, dass PE_FrameButtonTool und PE_IndicatorArrowDown im Baum enthalten sind, da der Java-Stil sie zeichnet, aber Sie können sie getrost weglassen, wenn Sie es vorziehen. Die Struktur kann auch anders sein. QCommonStyle So zeichnet z. B. der Java-Stil sowohl PE_IndicatorButtonDropDown als auch PE_IndicatorArrowDown in CE_ToolButton.

Wir haben auch ein Bild einer Werkzeugschaltfläche, bei der wir die Begrenzungsrechtecke der Unterelemente und die Untersteuerelemente umrissen haben.

Hier ist die Zustandstabelle für Werkzeugschaltflächen:

ZustandSetzen Wenn
State_AutoRiseDie Werkzeugschaltfläche hat die Eigenschaft autoRise eingestellt.
State_RaisedDie Schaltfläche ist nicht versenkt (d. h., sie wurde mit der Maus markiert oder gedrückt).
State_SunkenDie Schaltfläche ist gesenkt.
State_OnDie Schaltfläche ist prüfbar und geprüft.

QStyleOptionToolButton enthält auch die folgenden Mitglieder:

MitgliedInhalt
arrowTypeEin Qt::ArrowType enum-Wert, der die Richtung des Pfeils der Schaltfläche enthält (wenn ein Pfeil anstelle eines Symbols verwendet werden soll).
EigenschaftenFlags des QStyleOptionToolButton::ButtonFeature enum, die beschreiben, ob die Schaltfläche einen Pfeil, ein Menü und/oder eine Popup-Verzögerung hat.
SchriftartDie QFont der Beschriftung des Buttons.
SymbolDie QIcon der Werkzeugschaltfläche.
iconSizeDie Icon-Größe des Icons der Schaltfläche.
posDie Position der Schaltfläche, wie von QWidget::pos() angegeben.
textDer Text der Schaltfläche.
toolButtonStyleEin Qt::ToolButtonStyle enum-Wert, der entscheidet, ob die Schaltfläche das Symbol, den Text oder beides anzeigt.

Symbolleisten

Symbolleisten sind Teil von main window framework und arbeiten mit der QMainWindow zusammen, zu der sie gehören, während sie ihre Stiloptionen aufbauen. Ein Hauptfenster hat 4 Bereiche, in denen Symbolleisten platziert werden können. Sie befinden sich neben den vier Seiten des Fensters (d. h. Norden, Süden, Osten und Westen). Innerhalb jedes Bereichs kann es mehr als eine Zeile von Symbolleisten geben; eine Zeile besteht aus Symbolleisten mit gleicher Ausrichtung (vertikal oder horizontal), die nebeneinander angeordnet sind.

Toolbars in Qt bestehen aus drei Elementen: CE_ToolBar QMainWindowLayout, PE_IndicatorToolBarHandle und PE_IndicatorToolBarSeparator. QMainWindowLayout berechnet die Begrenzungsrechtecke (d. h. Position und Größe der Symbolleisten und ihres Inhalts). Das Hauptfenster verwendet auch die sizeHint() der Elemente in den Symbolleisten, um die Größe der Leisten zu berechnen.

Hier ist der Elementbaum für QToolBar dargestellt:

Die gestrichelten Linien zeigen an, dass QToolBar eine Instanz von QToolBarLayout enthält und dass QToolBarSeparators von QToolBarLayout gehalten wird. Wenn die Symbolleiste schwebend ist (d.h. ein eigenes Fenster hat), wird das Element PE_FrameMenu gezeichnet, andernfalls zeichnet QToolBar CE_ToolBar .

Hier ist ein Bild einer Symbolleiste im Java-Stil:

QToolBarSaparator verwendet QStyleOption für seine Stiloption. Er setzt das State_Horizontal Flag, wenn die Symbolleiste, in der er sich befindet, horizontal ist. Andernfalls wird initFrom() verwendet.

Die Stiloption für QToolBar ist QStyleOptionToolBar. Das einzige gesetzte Statusflag (neben den allgemeinen Flags) ist State_Horizontal, wenn die Leiste horizontal ist (d. h. im nördlichen oder südlichen Bereich der Symbolleiste). Die Mitgliedsvariablen der Option style sind:

MitgliedInhalt
EigenschaftenHält fest, ob die Leiste in einem Wert des ToolBarFeature beweglich ist, der entweder Movable oder None ist.
lineWidthDie Breite des Werkzeugleistenrahmens.
midLineWidthDiese Variable wird derzeit nicht verwendet und ist immer 0.
positionOfLineDie Position der Werkzeugleistenlinie innerhalb des Werkzeugleistenbereichs, zu dem sie gehört.
positionWithinLineDie Position der Symbolleiste innerhalb der Symbolleistenlinie.
toolBarAreaDer Bereich der Symbolleiste, in dem sich die Symbolleiste befindet.

Menüs in Qt sind in QMenu implementiert. QMenu führt eine Liste von Aktionen, die es als Menüpunkte zeichnet. Wenn QMenu Malereignisse empfängt, berechnet es die Größe der einzelnen Menüpunkte und zeichnet sie einzeln mit CE_MenuItem. Menüpunkte haben kein separates Element für ihre Beschriftung (Inhalt), so dass alle Zeichenvorgänge in CE_MenuItem ausgeführt werden. Das Menü zeichnet auch den Rahmen des Menüs mit PE_FrameMenu. Es zeichnet auch CE_MenuScroller, wenn der Stil Scrollen unterstützt. CE_MenuTearOff wird gezeichnet, wenn das Menü zu groß für sein Begrenzungsrechteck ist.

Im Stil-Strukturbaum ist auch QMenu enthalten, da es ebenfalls stilbezogene Aufgaben übernimmt. Die Begrenzungsrechtecke der Menüelemente werden für den Größenhinweis des Menüs und bei der Anzeige oder Größenänderung des Menüs berechnet.

Die Elemente CE_MenuScroller und CE_MenuTearOff werden von QCommonStyle verwaltet und nur angezeigt, wenn das Menü zu groß ist, um auf den Bildschirm zu passen. PE_FrameMenu wird nur für Pop-up-Menüs gezeichnet.

QMenu berechnet die Rechtecke auf der Grundlage seiner Aktionen und ruft CE_MenuItem und CE_MenuScroller auf, wenn der Stil dies unterstützt.

Es ist auch üblich, PE_IndicatorCheckBox (anstelle von PE_IndicatorMenuCheckMark) und PE_IndicatorRadioButton zum Zeichnen von ankreuzbaren Menüpunkten zu verwenden; wir haben sie nicht in den Stilbaum aufgenommen, da dies optional ist und von Stil zu Stil variiert.

Die Stiloption für Menüpunkte ist QStyleOptionMenuItem. Die folgenden Tabellen beschreiben die Statusflags und andere Elemente.

ZustandSetzen Wenn
State_SelectedDie Maus befindet sich über der Aktion und die Aktion ist kein Trennzeichen.
State_SunkenDie Maus wird auf dem Menüpunkt gedrückt.
State_DownArrowWird gesetzt, wenn der Menüpunkt ein Menü-Scroller ist und das Menü nach unten scrollt.
MitgliedInhalt
checkTypeEin Wert des CheckType enum, der entweder NotCheckable, Exclusive oder NonExclusive ist.
geprüftBoolescher Wert, der true ist, wenn der Menüpunkt markiert ist.
SchriftartDie QFont, die für den Text des Menüelements verwendet wird.
SymbolDie QIcon des Menüeintrags.
maxIconWidthDie maximal zulässige Breite für das Symbol.
menuHasCheckableItemsBoolescher Wert, der true ist, wenn mindestens ein Eintrag im Menü überprüfbar ist.
menuItemTypeDer Typ des Menüeintrags. Dies ist ein Wert des MenuItemType.
menuRectDas Begrenzungsrechteck für das QMenu, in dem sich der Menüpunkt befindet.
tabWidthDies ist der Abstand zwischen dem Text des Menüpunkts und der Verknüpfung.
textDer Text des Menüeintrags.

Die Einstellung der Stiloption für CE_MenuTearOff und CE_MenuScroller verwendet auch QStyleOptionMenuItem; sie setzen nur die Variable menuRect zusätzlich zu den gemeinsamen Einstellungen mit QStyleOption's initFrom().

QMenuBar verwendet den Stil, um jeden Menüleisteneintrag und den leeren Bereich der Menüleiste zu zeichnen. Die Pulldown-Menüs selbst sind QMenus (siehe Menüs). Es folgt der Stilelementbaum für die Menüleiste:

Das Panel und der leere Bereich werden nach den Menüelementen gezeichnet. Die QPainter, die QMenuBar an den Stil sendet, hat die Begrenzungsrechtecke der Elemente ausgeschnitten (d.h. Clip-Region), so dass Sie sich nicht darum kümmern müssen, über die Elemente zu zeichnen. Die Pixelmetriken in QMenuBar werden verwendet, wenn die Begrenzungsrechtecke der Menüleistenelemente berechnet werden.

QStyleOptionMenuItem wird für Menüleistenelemente verwendet. Die Mitglieder, die von QMenuBar verwendet werden, sind in der folgenden Tabelle beschrieben:

MitgliedInhalt
menuRectDas Begrenzungsrechteck der gesamten Menüleiste, zu der der Eintrag gehört.
textDer Text des Eintrags.
SymbolDas Icon des Menüpunkts (es ist nicht üblich, dass Stile dieses Icon zeichnen).

QStyleOptionMenuItem wird auch zum Zeichnen von CE_EmptyMenuBarArea verwendet.

QStyleOptionFrame wird für das Zeichnen des Panelrahmens verwendet. lineWidth ist auf PM_MenuBarPanelWidth eingestellt. midLineWidth ist derzeit immer auf 0 eingestellt.

Elementansicht Kopfzeilen

Dies ist der Stil, der die Kopfzeilen der Elementansichten von Qt zeichnet. Die Elementansichten behalten die Abmessungen der einzelnen Abschnitte bei. Beachten Sie auch, dass die Delegierten den Stil verwenden können, um Dekorationen und Rahmen um Elemente zu zeichnen. QItemDelegate So zeichnet zum Beispiel PE_FrameFocusRect und PE_IndicatorItemViewItemCheck.

Hier ist eine QTableWidget, die die Begrenzungsbereiche eines Java-Headers zeigt:

QHeaderView verwendet CT_HeaderSection, PM_HeaderMargin und PM_HeaderGripMargin für Größen- und Treffertestberechnungen. PM_HeaderMarkSize wird derzeit von Qt nicht verwendet. QTableView zeichnet die Schaltfläche in der oberen linken Ecke (d.h. den Bereich, in dem sich die vertikalen und horizontalen Kopfzeilen schneiden) als CE_Header.

Die Stiloption für Kopfzeilenansichten ist QStyleOptionHeader. Die Ansicht zeichnet jeweils einen Kopfzeilenabschnitt, die Daten beziehen sich also auf den gezeichneten Abschnitt. Ihr Inhalt ist:

MitgliedInhalt
SymbolDas Icon der Kopfzeile (für den Abschnitt, der gerade gezeichnet wird).
iconAusrichtungDie Ausrichtung (Qt::Alignment) des Icons in der Kopfzeile.
AusrichtungEin Qt::Orientation Wert, der bestimmt, ob die Kopfzeile horizontal über der Ansicht oder vertikal auf der linken Seite ist.
PositionEin Wert von QStyleOptionHeader::SectionPosition, der die Position der Kopfzeile im Verhältnis zu den anderen Abschnitten angibt.
AbschnittEnthält den Abschnitt, der gerade gezeichnet wird.
ausgewähltePositionEin QStyleOptionHeader::SelectedPosition Wert, der die Position des ausgewählten Abschnitts relativ zu dem Abschnitt angibt, der gezeichnet wird.
sortIndicatorEin QStyleOptionHeader::SortIndicator Wert, der die Richtung beschreibt, in der der Sortierindikator des Abschnitts gezeichnet werden soll.
textDer Text des aktuell gezeichneten Abschnitts.
textAusrichtungDie Qt::Alignment des Textes innerhalb des Kopfbereichs.

Baumzweigindikatoren

Die Astindikatoren in einer Baumansicht werden durch den Stil mit PE_IndicatorBranch gezeichnet. Unter Indikatoren verstehen wir hier die Indikatoren, die die Beziehung zwischen den Knoten im Baum beschreiben. Die generische QStyleOption wird an den Stil zum Zeichnen dieser Elemente gesendet. Die verschiedenen Zweigarten werden durch Zustände beschrieben. Da es keine spezifische Stiloption gibt, stellen wir einfach die Statustabelle vor:

ZustandSetzen Wenn
State_SiblingDer Knoten im Baum hat einen Geschwisterknoten (d. h., es gibt einen weiteren Knoten in derselben Spalte).
State_ItemDieser Zweigindikator hat ein Element.
State_ChildrenDer Zweig hat Kinder (d.h. ein neuer Unterbaum kann am Zweig geöffnet werden).
State_OpenDer Zweigindikator hat einen geöffneten Teilbaum.

Die Baumansicht (und das Baum-Widget) verwenden den Stil, um die Zweige (Knoten) des Baums zu zeichnen.

QStyleOption wird verwendet, da der Stil für PE_IndicatorBranch je nach Art der Verzweigung gesetzte Statusflags hat.

Da es keine Baumstruktur für Zweigindikatoren gibt, stellen wir nur ein Bild eines Baums im Java-Stil dar. Jeder Zustand wird im Bild durch ein Rechteck in einer bestimmten Farbe markiert (d. h. die Rechtecke sind keine Begrenzungsrechtecke). Alle Kombinationen von Zuständen, die Sie kennen müssen, sind in dem Bild dargestellt.

Werkzeugkästen

PM_SmallIconSize für sizeHints.

QToolBox ist ein Container, der eine Sammlung von Widgets enthält. Er hat eine Registerkarte für jedes Widget und zeigt jeweils eines davon an. Der Werkzeugkasten legt die Komponenten, die er anzeigt (die Schaltflächen des Werkzeugkastens und das ausgewählte Widget) in einem QVBoxLayout an. Der Stilbaum für Werkzeugkästen sieht wie folgt aus:

Wir zeigen ein Bild eines Werkzeugkastens im Stil Plastique:

Alle Elemente haben im Plastique-Stil und in den anderen eingebauten Qt-Stilen die gleichen Begrenzungsrechtecke.

Die Stiloption für Werkzeugkästen ist QStyleOptionToolBox. Sie enthält den Text und das Symbol für den Inhalt des Werkzeugkastens. Der einzige Status, der durch QToolBox gesetzt wird, ist State_Sunken, der gesetzt wird, wenn der Benutzer mit der Maus auf einen Tabulator drückt. Die übrigen Mitglieder von QStyleOptionToolBox sind:

MitgliedInhalt
SymbolDas Symbol auf der Registerkarte der Toolbox.
TextDer Text auf der Registerkarte "Werkzeugkasten".

Größe Griff

Der Size Grip berechnet seinen Size Hint mit CT_SizeGrip. Die Pixelmetrik PM_SizeGripSize wird derzeit von Qt nicht verwendet. Es folgt der Elementbaum für ein Bild im Plastique-Stil von QSizeGrip:

Wir zeigen den Größenhinweis in der unteren rechten Ecke von QMainWindow an.

Die Stiloption für den Größengriff, QStyleOptionSizeGrip, hat ein Mitglied neben den gemeinsamen Mitgliedern von QStyleOption:

MitgliedInhalt
EckeEin Qt::Corner -Wert, der beschreibt, in welcher Ecke eines Fensters (oder ähnlichem) sich der Griff befindet.

Gummiband

Der Stilbaum von QRubberBand besteht aus zwei Knoten.

Wir zeigen ein Bild eines Fensters im Java-Stil, das in QMdiArea mit einem Gummiband bewegt wird:

Die Stiloption für Gummibänder ist QStyleOptionRubberBand. Ihre Mitglieder sind:

MitgliedInhalt
undurchsichtigBoolescher Wert, der true ist, wenn das Gummiband in einem undurchsichtigen Stil (d.h. in einer Farbe) gezeichnet werden muss.
FormEin QRubberBand::Shape enum Wert, der die Form des Bandes enthält (entweder ein Rechteck oder eine Linie).

Dock-Widgets

Wenn das Dock-Widget seinen Inhalt anlegt, fragt es den Stil nach diesen Pixelmetriken: PM_DockWidgetSeparatorExtent, PM_DockWidgetTitleBarButtonMargin, PM_DockWidgetFrameWidth und PM_DockWidgetTitleMargin. Es berechnet auch die Begrenzungsrechtecke der Schaltflächen float und close mit SE_DockWidgetCloseButton und SE_DockWidgetFloatButton.

Die gestrichelten Linien zeigen an, dass der Absender Instanzen des Empfängers des Pfeils beibehält (d. h., es ist kein Stilelement, das gezeichnet werden muss). Das Dock-Widget zeichnet PE_frameDockWidget nur, wenn es von seinem Hauptfenster abgetrennt ist (d. h., es ist ein Fenster der obersten Ebene). Wenn es angedockt ist, zeichnet es den Indikator für die Größenänderung des Dock-Widgets. Wir zeigen ein Andock-Widget sowohl im angedockten als auch im schwebenden Zustand im Stil plastique:

Die Stiloption ist QStyleOptionDockWidget:

MitgliedInhalt
schließbarBoolescher Wert, der angibt, ob das Dock-Fenster geschlossen werden kann.
schwebendBoolescher Wert, der angibt, ob das Andockfenster schweben kann (d. h. sich von dem Hauptfenster, in dem es sich befindet, lösen kann).
beweglichBoolescher Wert, der angibt, ob das Fenster verschiebbar ist (d. h., ob es in andere Bereiche des Dock-Widgets verschoben werden kann).
TitelDer Titeltext des Andockfensters.

Für die Schaltflächen wird QStyleOptionButton verwendet (siehe Werkzeug-Schaltflächen für eine Beschreibung des Inhalts). Der Handle für die Größenänderung des Dock-Widgets hat einen einfachen QStyleOption.

© 2025 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.