スタイルとスタイル・アウェア・ウィジェット

スタイル(QStyle を継承したクラス)はウィジェットの代わりに描画を行い、GUIのルック&フィールをカプセル化します。QStyle クラスは、GUI のルック&フィールをカプセル化する抽象基底クラスです。Qt の組み込みウィジェットは、ほぼすべての描画をこのクラスで行い、同等のネイティブウィジェットとまったく同じように見えるようにしています。

Qtには組み込みスタイルが用意されています。特定のプラットフォームでのみ利用可能なスタイルもあります。カスタム・スタイルはプラグインとして、またはQStyleFactory::create() で特定のスタイル・クラスのインスタンスを作成し、QApplication::setStyle() で設定することで利用できるようになります。

スタイルのカスタマイズ

既存のスタイルをカスタマイズするには、QProxyStyle を継承し、必要な仮想メソッドを再実装します。QProxyStyle では、特定のベース・スタイルを指定することもできますが、ベース・スタイルが未指定の場合は自動的にアプリケーション・スタイルが使用されます。前者はベース・スタイルを完全に制御でき、カスタマイズが特定のスタイル動作を期待する場合に最適です。一方、後者はプラットフォームに依存せず、ネイティブ・プラットフォームのスタイルをデフォルトとするアプリケーション・スタイルをカスタマイズする方法を提供します。

カスタム スタイルの実装

QCommonStyle は、完全なカスタム・スタイルを実装するための便利なベースを提供します。アプローチは と同じですが、代わりに を継承し、適切な仮想メソッドを再実装します。完全なカスタム・スタイルの実装はやや複雑であるため、この概要を説明します。個々の Qt ウィジェットにスタイルを設定する方法をステップバイステップで説明します。 仮想関数、メンバ変数、および列挙を調べます。QProxyStyle QCommonStyle QStyle

このドキュメントの個々のウィジェットのスタイリングに関係しない部分は、順番に読むことを意図しています。ウィジェットの説明は、スタイルを実装する際の参考にすることができます。ただし、Qt のソースコードを参照する必要がある場合もあります。このドキュメントを読めば、スタイリング・プロセスの順序が明確になり、関連するコードを見つけるのに役立つはずです。

スタイルを意識したウィジェット(つまり、描画されるスタイルに適合したウィジェット)を開発するには、現在のスタイルを使ってウィジェットを描画する必要があります。このドキュメントでは、ウィジェットの描画方法と、スタイルがウィジェットに与える可能性について説明します。

ウィジェット スタイリング用クラス

これらのクラスは、アプリケーションの外観とスタイルをカスタマイズするために使用します。

QColor

RGB、HSV、またはCMYK値に基づく色

QColorSpace

色空間の抽象化

QColorTransform

色空間間の変換

QCommonStyle

GUI共通のルック&フィールのカプセル化

QCursor

任意の形状のマウスカーソル

QFont

テキストの描画に使用するフォントのクエリを指定する

QFontDatabase

基本的なウィンドウシステムで利用可能なフォントに関する情報

QFontInfo

フォントに関する一般的な情報

QGraphicsAnchor

QGraphicsAnchorLayout内の2つのアイテム間のアンカーを表します。

QGraphicsAnchorLayout

グラフィックスビューでウィジェット同士をアンカーするためのレイアウト

QPalette

各ウィジェットの状態のためのカラーグループを含む

QStyle

GUIのルック&フィールをカプセル化する抽象基底クラス

QStyleFactory

QStyleオブジェクトの作成

QStyleHintReturn

基本データ型以上を返すスタイル・ヒント

QStyleHintReturnMask

QRegion を返すスタイルヒント

QStyleHintReturnVariant

QVariantを返すスタイル・ヒント

QStyleOption

QStyle 関数で使用されるパラメータを格納します。

QStylePainter

ウィジェット内にQStyle要素を描画するための便利なクラス

QStyleの実装

QStyle の API には、ウィジェットを描画する関数、一般的で困難なタスク(スライダ・ハンドルの位置の計算など)を実行する静的ヘルパー関数、描画中に必要なさまざまな計算を行う関数(ウィジェットのサイズ・ヒントの計算など)が含まれています。また、このスタイルは、一部のウィジェットのコンテンツのレイアウトにも役立ちます。さらに、描画に使用するQBrushes を含むQPalette を作成します。

QStyle 要素とは、ウィジェットや、プッシュボタンベベル、ウィンドウフレーム、スクロールバーなどのウィジェットパーツです。ほとんどのdraw関数は4つの引数を取ります:

  • 描画するグラフィカル要素を指定する列挙値
  • その要素をどこでどのように描画するかを指定するQStyleOption
  • 要素の描画に使用するQPainter
  • 描画が実行されるQWidget (オプション)

ウィジェットがスタイルに要素の描画を要求する場合、スタイルに描画に必要な情報を含むクラスであるQStyleOption を提供します。QStyleOption のおかげで、ウィジェットのコードをリンクせずにQStyle にウィジェットを描画させることができます。このため、QStyle の描画関数をあらゆるペイント・デバイスで使用することができます。つまり、QComboBox だけでなく、あらゆるウィジェットにコンボボックスを描画することができます。

ウィジェットは、スタイルが特殊効果(macOSのデフォルト・ボタンのアニメーションなど)を実行するために必要な場合に最後の引数として渡されますが、必須ではありません。

QStyle最後に、パレットの使用方法について説明します。

アイテムビューのアイテムは、Qt のデリゲートによって描画されます。アイテム ビューのヘッダーは、依然としてスタイルによって描画されます。Qt のデフォルトのデリゲートであるQStyledItemDelegate は、現在のスタイルによって部分的にアイテムを描画します。このデリゲートは、チェックボックスのインジケータを描画し、アイテムを構成する要素の外接矩形を計算します。このドキュメントでは、QStyle サブクラスの実装方法のみを説明します。QStyledItemDelegate でサポートされている以外のデータ型のサポートを追加したい場合は、カスタムのデリゲートを実装する必要があります。デリゲートは、個々のウィジェットに対してプログラムで設定しなければならないことに注意してください(つまり、デフォルトのデリゲートをプラグインとして提供することはできません)。

スタイル要素

スタイル・エレメントは、GUIのグラフィカルな部分です。ウィジェットは、スタイル要素の階層(またはツリー)で構成されます。たとえば、スタイルが(QPushButton などから)プッシュ ボタンの描画要求を受け取ると、ラベル(テキストとアイコン)、ボタンのベベル、フォーカス フレームが描画されます。ボタンのベベルは、ベベルを囲むフレームと、後で説明する他の2つの要素で構成されます。以下は、プッシュボタンの要素ツリーの概念図です。QPushButton 、個々のウィジェットを説明するときに、実際のツリーを見ることになる。

ウィジェットは、必ずしもスタイルに 1 つの要素だけを描画するように指定して描画されるわけではありません。ウィジェットは、スタイルに複数の呼び出しを行い、異なる要素を描画することができます。例えば、QTabWidget は、タブとフレームを個別に描画します。

要素には、プリミティブ要素、コントロール要素、複合コントロール要素の3種類があります。要素はComplexControlControlElementPrimitiveElement 列挙体によって定義されます。各要素列挙型の値には、その型を識別するための接頭辞があります:複合要素はCC_ 、制御要素はCE_ 、プリミティブ要素はPE_ 。以下の3つのセクションでは、各要素の定義と、それらを使用するウィジェットの例を示します。

QStyle クラスの説明には、これらの要素のリストと、ウィジェットのスタイリングにおける役割が記載されています。個々のウィジェットをスタイリングするときに、これらの要素がどのように使用されるかを見ていきます。

プリミティブ要素

プリミティブ要素は、複数のウィジェットで共通に使用される GUI 要素です。例えば、フレーム、ボタンのベベル、スピンボックス、スクロールバー、コンボボックスの矢印などです。プリミティブ要素は単独で存在することはできず、常に大きな構成要素の一部です。これらはユーザーとのインタラクションには関与せず、GUIにおける受動的な装飾となります。

コントロール要素

コントロール要素は、ユーザーに対してアクションを実行したり、情報を表示したりします。コントロール・エレメントの例としては、プッシュ・ボタン、チェック・ボックス、テーブルやツリー・ビューのヘッダー・セクションなどがあります。コントロール要素は、プッシュボタンのような完全なウィジェットとは限らず、タブバーのタブやスクロールバーのスライダーのようなウィジェットの一部であることもあります。受動的ではなく、ユーザーとのインタラクションで機能を満たすという点で、プリミティブ要素とは異なります。複数の要素で構成されるコントロールでは、多くの場合、スタイルを使用して要素の境界矩形を計算します。使用可能なサブ要素は、SubElement enum で定義されます。この enum は外接矩形の計算にのみ使用されます。サブ要素は、プリミティブ要素、コントロール要素、複合要素のように描画されるグラフィカル要素ではありません。

複合コントロール要素

複合コントロール要素にはサブコントロールが含まれる。複雑なコントロールは、ユーザーがマウスでどこを操作し、どのキーボード・キーが押されたかによって動作が異なる。これは、マウスがどのサブコントロール(もしあれば)の上にあるか、押されているかに依存します。複雑なコントロールの例としては、スクロールバーやコンボボックスがあります。スクロールバーでは、マウスを使ってスライダーを動かし、上下のボタンを押すことができます。使用可能なサブコントロールは、SubControl enumで定義されます。

スタイルでは、描画だけでなく、マウスを押したときにどのサブコントロールが押されたかという情報をウィジェットに提供する必要があります。たとえば、QScrollBar は、ユーザーが押したのがスライダーなのか、スライダーの溝なのか、ボタンのどれかなのかを知る必要があります。

サブコントロールは、前のセクションで説明したコントロール要素と同じではないことに注意してください。スタイルを使用してサブコントロールを描画することはできません。スタイルは、サブコントロールが描画されるべき境界矩形を計算するだけです。しかし、複雑な要素では、コントロール要素やプリミティブ要素を使用してサブコントロールを描画するのが一般的であり、これはQtの組み込みスタイルやJavaスタイルでも頻繁に使用されるアプローチです。例えば、Javaスタイルでは、PE_IndicatorCheckBoxを使用してグループボックスのチェックボックスを描画しています(これはCC_GroupBox のサブコントロールです)。サブコントロールの中には、同等のコントロール要素を持つものがあります。例えば、スクロール・バーのスライダーです(SC_SCrollBarSliderCE_ScrollBarSlider)。

その他のQStyleタスク

前述のように、スタイル要素とウィジェットは、スタイルを使用してサブ要素とサブコントロールの境界矩形を計算します。ピクセル メトリック(画面ピクセル単位のスタイル依存サイズ)も、描画時の測定に使用されます。利用可能な矩形とピクセルメトリックは、QStyle の3つの列挙型で表現されています:SubElementSubControlPixelMetric 。これらの列挙型の値は SE_、SC_、PM_ で始まるため、簡単に識別できます。

スタイルにはスタイルのヒントも含まれており、これはStyleHint enum の値として表されます。すべてのウィジェットが同じ機能を持ち、異なるスタイルで表示されるわけではありません。たとえば、メニューの項目が画面上の1列に収まらない場合、スクロールをサポートするスタイルもあれば、すべての項目が収まるように複数の列を描画するスタイルもあります。

スタイルには通常、メッセージボックスやファイルダイアログなどの標準画像(警告、質問、エラー画像など)のセットがあります。QStyleStandardPixmap enum を提供します。その値は標準画像を表します。Qt のウィジェットはこれらを使用するため、カスタムスタイルを実装する場合は、実装するスタイルで使用する画像を指定する必要があります。

スタイルは、レイアウト内のウィジェット間の間隔を計算します。スタイルがこれらの計算を処理する方法は 2 つあります。PM_LayoutHorizontalSpacingPM_LayoutVerticalSpacing 、これはJavaスタイルが行う方法です(QCommonStyle )。また、レイアウトのこの部分をさらに制御する必要がある場合は、QStyle::layoutSpacing ()とQStyle::layoutSpacingImplementation()を実装することもできます。これらの関数では、異なるサイズ・ポリシー(QSizePolicy::Policy)のコントロール・タイプ(QSizePolicy::ControlType)と、該当するウィジェットのスタイル・オプションに基づいて、スペーシングを計算することができます。

スタイル・オプション

QStyleOption のサブクラスには、個々の要素のスタイル設定に必要なすべての情報が含まれています。スタイル・オプションはインスタンス化され、通常はスタック上に置かれ、QStyle 関数の呼び出し元によって記入されます。描画されるものによって、スタイルは異なるスタイル・オプション・クラスを期待します。たとえば、QStyle::PE_FrameFocusRect 要素はQStyleOptionFocusRect 引数を必要とし、カスタム スタイルが使用できるカスタム サブクラスを作成できます。スタイル・オプションは、パフォーマンス上の理由からパブリック変数を保持します。

ウィジェットは、State enumによって定義される、いくつかの異なる状態になることができます。状態フラグのいくつかは、ウィジェットによって意味が異なりますが、State_Disabled のようにすべてのウィジェットに共通なものもあります。QStyleOption::initFrom() で共通の状態を設定するのはQStyleOption です。残りの状態は、個々のウィジェットによって設定されます。

最も重要なのは、スタイル・オプションに、描画するウィジェットのパレットと境界矩形が含まれていることです。たとえば、QPushButtonQCheckBox は、QStyleOptionButton をスタイル・オプションとして使用し、テキスト、アイコン、アイコンのサイズが含まれます。すべてのオプションの正確な内容は、個々のウィジェットを説明するときに説明します。

QStyleOption パラメータを取るQStyle 関数を再実装する場合、多くの場合、QStyleOption をサブクラス(例えば、QStyleOptionFocusRect )にキャストする必要があります。安全のため、qstyleoption_cast() を使用して、ポインタの型が正しいことを確認できます。オブジェクトの型が正しくない場合、qstyleoption_cast() はnullptr を返します。例えば、以下のコード・スニペットでは、ポインタの型が正しいことを確認しています:

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

次のコード・スニペットは、QStyle を使用して、カスタム・ウィジェットの paintEvent() からフォーカス矩形を描画する方法を示しています:

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);
}

次の例では、既存のスタイルから派生してグラフィック要素の外観をカスタマイズする方法を示します:

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 関数

QStyle クラスは、プリミティブ、コントロール、および複合要素を描画するための 3 つの関数を定義しています:drawPrimitive()、drawControl()、drawComplexControl()。関数は以下のパラメータを受け取ります:

  • 描画する要素の列挙値。
  • 要素の描画に必要な情報を含むQStyleOption
  • 要素を描画するためのQPainter
  • QWidget へのポインタ。通常は、要素が描画されるウィジェットです。

すべてのウィジェットが自分自身へのポインタを送るわけではありません。関数に送信されたスタイル・オプションに必要な情報が含まれていない場合は、ウィジェットの実装をチェックして、ウィジェットが自分自身へのポインタを送信しているかどうかを確認する必要があります。

QStyle クラスは、要素を描画するときに使用するヘルパー関数も提供します。drawItemText() 関数は、QPalette をパラメータとして、指定した矩形内にテキストを描画します。drawItemPixmap() 関数は、指定された境界矩形内に pixmap を配置するのに役立ちます。

その他のQStyle 関数は、描画を行う関数のためにさまざまな計算を行います。ウィジェットは、いくつかのスタイル要素を描画する場合、サイズヒントと境界矩形の計算にもこれらの関数を使用します。要素を描画する関数と同様に、ヘルパー関数は通常同じ引数を取ります。

  • subElementRect() 関数はSubElement enum 値を受け取り、サブ要素の外接矩形を計算します。スタイルはこの関数を使用して、要素のさまざまな部分を描画する場所を把握します。これは主に再利用のために行われます。新しいスタイルを作成する場合、スーパー クラスと同じサブ要素の位置を使用できます。
  • subControlRect ()関数は、複雑なコントロールのサブコントロールの外接矩形を計算するために使用します。新しいスタイルを実装するときは、subControlRect() を再実装し、スーパー・クラスとは異なる矩形を計算します。
  • pixelMetric() 関数は、ピクセル メトリックを返します。これは、スタイルに依存するサイズをスクリーン ピクセルで指定したものです。これはPixelMetric enum の値を取り、正しい測定値を返します。ピ ク セル メ ト リ ッ ク は、 必ず し も 静的な計測値であ る 必要はあ り ません。
  • hitTestComplexControl ()関数は、複合コントロールの中でマウス・ポインタが乗っているサブコントロールを返します。通常は、subControlRect ()を使用してサブコントロールの外接矩形を取得し、どの矩形にカーソルの位置が含まれているかを確認するだけです。

QStyle また、 () と () という関数もあります。すべてのウィジェットは、表示される前に 関数に送られ、非表示になると 関数に送られます。これらの関数を使用して、ウィジェットの属性を設定したり、スタイルで必要なその他の作業を行うことができます。例えば、マウスがウィジェットの上に来たことを知る必要がある場合、 ウィジェット属性を設定する必要があります。すると、 状態フラグがウィジェットのスタイル・オプションに設定されます。polish unpolish polish() unpolish() WA_Hover State_MouseOver

QStyle には、一般的で難しいタスクを実行する静的ヘルパー関数がいくつかあります。これらは、スライダーの値からスライダー・ハンドルの位置を計算したり、長方形を変換したり、逆レイアウトを考慮してテキストを描画したりできます。詳細は クラス・ドキュメントを参照してください。QStyle

QStyle 仮想関数を再インプリメントする場合の通常のアプローチは、スーパークラスとは異なる要素に対して処理を行うことです。他のすべての要素については、単にスーパークラスの実装を使用することができます。

パレット

各スタイルは、ウィジェットの描画に使用する色、つまりQBrush のパレットを提供します。ウィジェットの状態 (QPalette::ColorGroup) に応じて、アクティブ (キーボード フォーカスを持つウィンドウ内のウィジェット)、非アクティブ (他のウィンドウに使用されるウィジェット)、およびディスエーブル (無効にされたウィジェット) の各色のセットがあります。状態は、State_ActiveState_Enabled 状態フラグをクエリすることで見つけることができる。各セットには、QPalette::ColorRole enumで指定された特定の色の役割が含まれています。役割は、どのような状況で色を使用するかを記述します(例えば、ウィジェットの背景、テキスト、ボタンなど)。

色の役割をどのように使用するかは、スタイル次第です。例えば、スタイルがグラデーションを使用する場合、パレットカラーを使用し、QColor::darker ()とQColor::lighter ()で濃くしたり薄くしたりしてグラデーションを作成することができます。一般的に、パレットで提供されていないブラシが必要な場合は、パレットから派生させるようにしましょう。

QPaletteパレットを提供する.palette()は、さまざまなウィジェットの状態と色の役割のための色を格納します。スタイルのパレットは、standardPalette() によって返されます。新しいスタイルがアプリケーション (QApplication::setStyle()) やウィジェット (QWidget::setStyle()) に設定された場合、標準パレットは自動的にインストールされないため、 (QApplication::setPalette()) や (QWidget::setPalette()) でパレットを設定する必要があります。

アプリケーションや個々のウィジェットは、独自のパレットを設定し、そのスタイルのパレットを描画に使用することができるため、色をハードコードすることは推奨されません。Qtのウィジェットには、独自のパレットを設定するものはありません。Javaスタイルではいくつかの色をハードコードしていますが、これは作者の判断によるものであり、推奨されるものではありません。もちろん、スタイルがどのようなパレットでも見栄えが良くなるように意図されているわけではありません。

実装の問題

スタイルを実装する際には、考慮すべきいくつかの問題があります。ここでは、実装に関するいくつかのヒントとアドバイスを示します。

スタイルを実装する場合、ウィジェットのコードとベース・クラスとその祖先のコードに目を通す必要があります。これは、ウィジェットによってスタイルの使い方が異なるためで、異なるスタイルの仮想関数での実装が描画状態に影響を与える可能性があるためです(QPainter の状態を復元せずに変更したり、適切なピクセル メトリックやサブ要素を使用せずに一部の要素を描画したりするなど)。

QStyle::sizeFromContents ()関数でウィジェットのサイズ案を変更せず、QCommonStyle の実装に任せることをお勧めします。ウィジェットのレイアウトがさまざまなスタイルでかなり異なって見えると、アプリケーションの開発が困難になる可能性があります。

Javaスタイル

Javaのデフォルトのルック&フィール(以前はMetalと呼ばれていました)に似たスタイルを実装しました。これは、実装が比較的簡単であり、この概要ドキュメントのスタイルを構築したかったためです。シンプルに保つため、またあまり広範囲にならないようにするため、スタイルを多少簡略化しましたが、Qt はスタイルの完全なコピーを作成することができます。しかし、Qtの一部としてこのスタイルを実装する具体的な計画はありません。

このセクションでは、いくつかの実装上の問題点を見ていきます。最後に、Java ウィジェットのスタイリングに関する完全な例を示します。このドキュメントでは、例とウィジェットのイメージにJavaスタイルを使用し続けます。実装自体は多少複雑なので、通読することは意図していません。

設計と実装

スタイルを設計する最初のステップは、ベース・クラスを選択することでした。私たちはQCommonStyle のサブクラスを選びました。このクラスは、実際の描画を行う以外に必要な機能のほとんどを実装しています。

スタイルは1つのクラスで実装されています。このようにしたのは、すべてのコードを1つのファイルにまとめておくと便利だからです。また、オブジェクトのインスタンス化が少なくて済むので、最適化に関しても有利です。また、関数の中でどの要素を描画するかを識別するためにスイッチを使用することで、関数の数を最小限に抑えています。その結果、関数は大きくなりますが、スイッチで要素ごとにコードを分割しているので、それでもコードは読みやすいはずです。

限界とJavaとの違い

Javaスタイルでは、すべての要素を完全に実装していません。こうすることで、コードの量と複雑さを減らしている。一般的に、このスタイルは、このスタイル概要ドキュメントの実用的な例として意図されたものであり、Qt 自体の一部ではありません。

すべてのウィジェットにすべてのステートが実装されているわけではありません。これは、例えばState_Disabled のような一般的な状態も同様です。しかし、各状態は、少なくとも1つのウィジェットに実装されています。

私たちは、スライダーの下の目盛りだけを実装しました。フラットなプッシュ・ボタンも実装していません。タイトル・バーやドック・ウィンドウのタイトルが、その内容に対して小さくなりすぎるようなケースは扱わず、単純にサブ・コントロールを重ねて描画しています。

Java フォントのエミュレートは試していません。Java と Qt は非常に異なるフォント・エンジンを使っているので、この概要のためにこのスタイルを例として使うだけなので、努力する価値はないと考えています。

例えば、ボタンのベベル、ツールバー、チェックボックスなどに使用される線形グラデーションについては、色をハードコーディングしました(QPalette は使用しません)。これは、Javaパレットがこれらの色を生成できないためです。Javaは、ウィジェットのカラー・グループや役割に基づいてこれらの色を変更しない(パレットに依存しない)ので、どのような場合でも問題はありません。

スタイルを設定するのは Qt のウィジェットです。例えば、QToolBox のように、Javaには全く存在しないウィジェットもあります。また、Javaウィジェットにはない要素を含むものもあります。ツリー・ウィジェットは後者の例で、Java の JTree にはヘッダーがありません。

スタイルは、逆レイアウトを扱いません。レイアウトの方向は左から右であると仮定します。QCommonStyle 、逆レイアウトのウィジェットを扱います。逆レイアウトを実装すると、サブ要素の位置を変更するウィジェットや、ラベルのテキスト・アラインメントを扱うウィジェットを更新する必要があります。

Javaチェック・ボックスのスタイリング

例として、Javaスタイルでのチェック・ボックスのスタイリングを調べます。完全なプロセスを説明し、Java スタイルと Qt クラスのすべてのコードを表示します。このドキュメントの残りの部分では、個々のウィジェットのソース・コードは調べません。ほとんどのウィジェットはチェックボックスと同じ構造になっています。チェックボックスのスタイリングに直接関係のないコードを削除するために、QCommonStyle のコードを多少編集しました。

まず、QCheckBox がどのようにチェックボックス用のスタイル・オプション(QStyleOptionButton )を構築するかを見ていきます:

    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();

まずQStyleOption に、すべてのウィジェットに共通な情報を持つオプションをinitFrom() でセットアップさせます。これについては後ほど説明する。

QStyleOption'のdown 変数は、ユーザがボックスを押し下げると、true になります。これは、ボックスがチェックされているかどうかにかかわらず、チェックボックスに当てはまります。トライステート・チェックボックスがあり、部分的にチェックされている場合、State_NoChange の状態が設定されます。ボックスがチェックされている場合はState_On が、チェックされていない場合はState_Off が設定されます。マウスがチェックボックスの上に置かれ、ウィジェットに属性Qt::WA_Hover が設定されている場合はState_MouseOver が設定されます。これはQStyle::polish() で設定します。さらに、スタイル・オプションには、ボタンのテキスト、アイコン、アイコンのサイズも含まれます。

initFrom() は、すべてのウィジェットに共通な属性でスタイル・オプションを設定します。ここでは、その実装を表示する:

    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();

State_Enabled は、ウィジェットが有効なときに設定されます。ウィジェットにフォーカスがあるとき、State_HasFocus フラグが設定されます。同様に、State_Active フラグは、ウィジェットがアクティブ・ウィンドウの子であるときに設定されます。State_MouseOver が設定されるのは、ウィジェットにWA_HoverEnabled windows フラグが設定されている場合だけである。State_HasEditFocus を含めるには、Qt でキーパッド ナビゲーションが有効になっている必要があります。

QStyleOption direction はレイアウトの方向、 はウィジェットの外接矩形(描画する領域)、 はウィジェットの描画に使用する 、 はウィジェットで使用するフォントのメトリックです。rect palette QPalette fontMetrics

チェックボックスの画像と、それにマッチするスタイル・オプションを与えます。

Javaスタイルのチェックボックス

上記のチェックボックスは、スタイル・オプションに以下の状態フラグを持ちます:

状態フラグ設定
State_SunkenYes
State_NoChangeいいえ
State_Onはい
State_Offいいえ
State_MouseOverはい
State_Enabledはい
State_HasFocusはい
State_KeyboardFocusChangeいいえ
State_Activeはい

QCheckBox は、スタイル・オプションoptQStylePainter p を用いてQWidget::paintEvent() で自身を描画する。QStylePainter クラスは、スタイル要素を描画するための便利なクラスです。特に、QStyle のメソッドをラップしています。QCheckBox は以下のように自分自身を描画します:

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

QCommonStyle はCE_CheckBox要素を扱います。 には2つのサブ要素があります:SE_CheckBoxIndicator (チェックされたインジケータ) と SE_CheckBoxContents (チェックボックスのラベルに使われる内容) です。 は、これらのサブ要素の境界矩形も実装しています。次に、 のコードを見てみましょう:QCheckBox QCommonStyle QCommonStyle

    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);
    }

コードの抜粋からわかるように、共通スタイルはCE_CheckBoxの2つのサブ要素の外接矩形を取得し、それらを描画します。チェックボックスにフォーカスがある場合は、フォーカス・フレームも描画されます。

JavaスタイルはCE_CheckBoxIndicatorを描画し、QCommonStyle はCE_CheckboxLabelを処理します。それぞれの実装を調べ、CE_CheckBoxLabelから始めます:

    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()) {
        const auto dpr = p->device()->devicePixelRatio();
        pix = btn->icon.pixmap(btn->iconSize, dpr,
                               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() は、レイアウト方向に従ってテキストの配置を調整します。次に、アイコンがあればそれを描画し、テキストのために残されたスペースを調整する。drawItemText() は、整列、レイアウト方向、ニーモニックを考慮してテキストを描画します。また、パレットを使って適切な色でテキストを描画する。

ラベルの描画はしばしばやや複雑になる。幸いなことに、通常は基本クラスで処理できる。Javaスタイルでは、独自のプッシュ・ボタン・ラベルを実装している。ラベル描画の再実装の例が必要なら、その実装を調べることができます。

次に、drawControl() のCE_CheckBoxIndicatorのJava実装を見てみましょう:

        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;

まず、ペインターの状態を保存します。これは常に必要というわけではありませんが、今回はQCommonStyle で PE_IndicatorCheckBox がコールされたときと同じ状態のペインタが必要です (もちろん、関数コールで状態を設定することもできます)。次にdrawButtonBackground() を使ってチェックボックスインジケータの背景を描画します。これは、プッシュボタンやチェックボックスの背景や枠を描画するヘルパー関数です。この関数については後述する。次に、マウスがチェックボックスの上にあるかどうかをチェックします。もしマウスがチェックボックスの上にあれば、チェックボックスが押されておらず、マウスがチェックボックスの上にあるときにJavaのチェックボックスが持つフレームを描画します。Javaはトライステート・ボックスを扱わないので、実装していないことに注意してください。

ここでは、インジケータにPNG画像を使用しています。ウィジェットが無効かどうかをチェックすることもできます。その場合は、インジケータを無効色にした別の画像を使用する必要があります。

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);
    }
}

チェック・ボックスが Java スタイルでどのようにスタイル設定されるかを、ウィジェットがペイント要求を取得してからスタイルがペイントされるまで見てきました。各ウィジェットがどのようにペイントされるかを詳しく学ぶには、ここで行ったようにコードを順を追って確認する必要があります。ただし、通常は、ウィジェットがどのスタイル要素を描画するかを知っていれば十分です。ウィジェットは、スタイル・オプションを構築し、スタイルを 1 回以上呼び出して、そのスタイルで構成されるスタイル要素を描画します。通常は、ウィジェットが取り得る状態とスタイル オプションのその他の内容、つまり次のセクションで説明する内容を知っていれば十分です。

ウィジェットのチュートリアル

このセクションでは、Qt のほとんどのウィジェットがどのようにスタイリングされているかを見ていきます。うまくいけば、独自のスタイルやウィジェットを開発する際の時間と労力を節約できます。ここでは、他の場所(ソースコードやスタイル関連クラスの説明を調べるなど)で得られない情報を見つけることはできません。

ほとんどの場合、Javaスタイルのウィジェットを例として使用しています。Java スタイルは、要素ツリーのすべての要素を描画しません。これは、Java スタイルではそのウィジェットの要素が表示されないためです。カスタム・ウィジェットでは、Javaスタイルに準拠した要素が必要になる可能性があるため、すべての要素がJavaスタイルに準拠した方法で実装されていることを確認します(ただし、実装をQCommonStyle に任せることを排除するものではありません)。

各ウィジェットについて、以下のように記述します:

  • スタイル・オプションのメンバ(変数など)の表。
  • ウィジェットに設定できるステートフラグ(QStyle::StateFlag)と、ステートが設定されるときのテーブル。
  • 要素ツリー(スタイル要素セクション参照)。
  • 要素がアウトライン化されたウィジェットのイメージ。

要素ツリーには、プリミティブ、コントロール、および複合スタイル要素が含まれます。要素ツリーをトップダウンで走査すると、要素が描画される順序が得られます。ノードには、そのノードの要素を描画するときに考慮すべきサブ要素の矩形、サブ制御要素、ピクセル メトリックを記述しています。

私たちのスタイリングに関するアプローチは、ウィジェットの描画を中心としています。描画時に使用されるサブエレメントの矩形、サブコントロール、ピクセルメトリクスの計算は、エレメントツリーのコンテンツとして記載されているだけです。ウィジェットでしか使われない矩形やピクセルメトリックがあることに注意してください。このため、ウォークスルーではこれらの計算を未処理のままにしています。たとえば、subControlRect ()とsizeFromContents ()関数は、しばしばsubElementRect ()を呼び出して外接矩形を計算します。このためにツリーを描くこともできる。しかし、これらの計算をどのように行うかは完全に個々のスタイルに任されており、特定の構造に従う必要はありません(Qtは特定の構造を強制しません)。ただし、適切なピクセル・メトリクスを使うようにする必要はあります。そのため、このドキュメントのサイズを制限するために、Java(または他の)スタイルで行われるツリーや計算については記述しないことにしました。

ツリーを調べるとき、異なるピクセルメトリック、サブエレメント長方形、サブコントロール長方形をどのように使うべきか、混乱するかもしれません。QStyle enum の説明を読んでもわからない場合は、QCommonStyle の実装を調べることをお勧めします。

ウィジェットの画像で輪郭を描く境界矩形のいくつかは等しくなります。その理由は、背景を描く要素もあれば、フレームやラベルを描く要素もあるからです。疑問があれば、QStyle の各要素の説明を確認してください。また、いくつかの要素はレイアウトのために存在します。

ウィジェットの共通プロパティ

いくつかの状態と変数は、すべてのウィジェットに共通です。これらはQStyleOption::initFrom() で設定します。すべての要素がこの関数を使用するわけではありません。スタイル・オプションを作成するのはウィジェットであり、いくつかの要素ではinitFrom() からの情報は必要ありません。

一般的な状態の表を以下に示します:

状態状態 Set When
State_Enabledウィジェットが無効でない場合に設定される (QWidget::setEnabled() を参照)
State_Focusウィジェットにフォーカスがある場合に設定 (QWidget::hasFocus() を参照)
State_KeyboardFocusChangeユーザがキーボードでフォーカスを変更したときに設定 (Qt::WA_KeyboardFocusChange を参照)
State_MouseOverマウスカーソルがウィジェットの上にある場合に設定されます。
State_Activeウィジェットがアクティブウィンドウの子ウィジェットである場合に設定します。
State_HasEditFocusウィジェットに編集フォーカスがある場合に設定

ウィジェットの他の共通メンバは以下の通りです:

メンバ内容
矩形描画する要素の外接矩形。これはウィジェットの外接矩形 (QWidget::rect()) に設定されます。
方向レイアウト方向。Qt::LayoutDirection enum の値。
palette要素を描画するときに使用するQPalette 。これはウィジェットのパレットに設定されます (QWidget::palette())。
fontMetricsウィジェットのテキスト描画時に使用するQFontMetrics

複合スタイル要素に使われる複合スタイルオプション(QStyleOptionComplex を継承したクラス)は、subControlsactiveSubControls の2つの変数を共有します。どちらの変数もQStyle::SubControl enum 値の OR の組み合わせである。これらは、複合コントロールがどのサブコントロールで構成され、これらのコントロールのどれが現在アクティブであるかを示す。

前述のように、スタイルはウィジェットのコンテンツのサイズを計算し、ウィジェットはそこからサイズのヒントを計算します。さらに、複合コントロールは、マウスがどのサブコントロール上にあるかをテストするためにもスタイルを使用します。

ウィジェットのリファレンス

さっそく、ウィジェットのウォークスルーを紹介します。各ウィジェットには独自のサブセクションがあります。

プッシュ ボタン

プッシュ ボタンのスタイル構造を以下に示します。ツリーをトップダウンで走査すると、要素が描画される順序が得られます。

プッシュボタンのスタイル構造

要素の境界に関するボタンのレイアウトは、スタイルによって異なります。このため、概念的なイメージを示すことは難しい。例えば、PE_PushButtonBevel は、QCommonStyle で、その中に含まれる要素を描画するために使われています:PE_FrameDefaultButton PE_FrameButtonBevel PE_PanelButtonCommand PE_PushButtonBevel はメニュー・インジケータの描画も担当している( は を描画)。QCommonStyle PE_IndicatorArrowDown

Javaスタイルでのプッシュ・ボタンの画像を以下に示します。色は、画像内の境界矩形を区切るために使われており、それ以外の目的では使われていません。これは、他のウィジェットの同様の画像にも当てはまります。

Java スタイルは、Qt で実装されている他のすべてのスタイルと同様に、PE_FrameButtonBevel を使用しません。通常、PE_DefaultFrame を持つボタンは、PE_PanelButtonCommand の矩形をPM_ButtonDefaultIndicator で調整します。CE_PushButtonLabel は、矩形をPM_DefaultFrameWidth で調整することで見つかります。

こ こ では、 プ ッ シ ュ ボ タ ン用の ス タ イルオプシ ョ ンQStyleOptionButton を調べてみま し ょ う 。QPushButton が style オプシ ョ ンで設定で き る 状態の表を以下に示 し ます:

状態設定される状態
State_Sunkenボタンが押されているか、メニューが押されている
State_Onボタンがチェックされている
State_Raisedボタンが平らでなく、下に押されていない

QStyleOptionButton の他のメンバーは次のとおり:

メンバー内容
特徴QStyleOptionButton::ButtonFeatures enumのフラグで、ボタンの様々なプロパティを記述する(enumを参照)。
アイコンボタンQIcon (もしあれば)
アイコンサイズアイコンのQSize
テキストQString ボタンのテキスト

チェックボタンとラジオボタン

ラジオボタンとチェックボタンの構造は同じです。QCheckBox 要素とピクセルのメトリック名を用いて構造を示す:

QStyleOptionButton は、チェックボタンとラジオボタンの両方のスタイルオプションとして使われます。まず、オプションで設定できる状態の表を示します:

状態状態 Set When
State_sunkenボ ッ ク ス が押下 さ れてい る
State_NoChangeボックスが部分的にチェックされている(トライステートチェックボックスの場合)。
State_Onボックスがチェックされている
State_Offボックスがチェックされていない

QStyleOptionButton クラスの他のメンバについては、プッシュ・ボタンを参照してください。

タブ

Qtでは、QTabBar 、タブの描画にスタイルを使用します。タブは、QTabBar を含むQTabWidget 内に存在するか、独立したバーとして存在します。バーがタブ・ウィジェットの一部でない場合は、独自のベースが描画されます。

QTabBar はタブを配置するため、スタイルはタブの配置を制御できません。ただし、タブを配置する際、バーはスタイルに と を要求します。これは、タブ バーのタブ ラベル(アイコンとテキスト)の最小サイズを超える余分な幅と高さです。また、タブ バーが を要求するように、スタイルがレイアウト前のタブ サイズにさらに影響を与えることもあります。バーの外接矩形は、それがウィジェットの一部である場合、タブ・ウィジェットによって決定されます(まだ を考慮しています)。PM_TabBarTabHSpace PM_TabBarTabVSpace CT_TabBarTab CT_TabBarTab

タブ バーは、すべてのタブが収まらない場合にタブ バーに表示されるボタンの描画を担当します。ボタンの配置はスタイルによって制御されませんが、ボタンはQToolButtonであるため、スタイルによって描画されます。

以下は、QTabWidgetQTabBar のスタイル構造です:

点線は、QTabWidget にタブ バーが含まれていることを示しますが、タブ バー自体は描画されません。QTabBar は、タブ ウィジェットの一部でない場合にのみ基本線を描画し、すべてのタブが収まらない場合にバーをスクロールする 2 つのツール ボタンを保持します。これらの要素ツリーについては、ツール ボタンを参照してください。また、ボタンはタブバーの子であるため、バーの後に描画されることに注意してください。タブの外接矩形は、ベースとPM_TabBarBaseOverlap だけ重なります。

Java スタイルのタブ・ウィジェットを示します:

Javaスタイルでは、タブ・バーの形状とラベルの境界矩形は、CE_TabBarTab と同じです。タブがタブ・ウィジェットのフレームと重なっていることに注目してください。タブ・バーのベース(描画されている場合)は、タブとフレームが重なる領域です。

タブのスタイル・オプション (QStyleOptionTab) には、タブを描画するために必要な情報が含まれています。このオプションには、タブバー内のタブの位置、選択されたタブの位置、タブの形状、テキスト、アイコン、アイコンのサイズが含まれます。

Javaスタイルのタブは重ならないので、共通スタイルのタブ・ウィジェットの画像も示します。タブを水平方向にオーバーラップさせたい場合は、CE_TabBarTabShape でタブを描画するときにそうします。タブの境界矩形はタブ・バーによって変更されません。タブは左から右へ北タブバーの形に、上から下へ東タブバーの形に描かれます。選択されたタブは最後に描画され、他のタブの上に簡単に描画できます(タブを大きくする場合)。

タブバーがタブに設定できる状態の表を以下に示す:

状態設定される状態
State_Sunkenタブがマウスで押されたとき。
State_Selectedそれが現在のタブである場合。
State_HasFocusタブバーにフォーカスがあり、タブが選択されている。

タブバーがアクティブでなくても、個々のタブが無効になっている場合があります。タブバーがアクティブであれば、タブはアクティブになります。

以下はQStyleOptionTab のメンバーの表である:

メンバー内容
コーナーウィジェットタブバーがどのコーナーウィジェットを持つかを示す CornerWidget 列挙型のフラグ。
アイコンタブのQIcon
アイコンサイズアイコンのQSize
位置タブの位置を示す TabPosition 列挙型の値。
タブがどの行にあるかを保持します。
selectedPositionSelectedPosition 列挙型の値で、選択されているタブが隣接しているか、タブであるかを示します。
shapeタブの角が丸いか三角か、タブの向きを示すQTabBar::Shape enum の値。
テキストタブのテキスト。

タブ・ウィジェットのフレームは、スタイル・オプションとしてQStyleOptionTabWidgetFrame を使用します。そのメンバをここに列挙する。共通フラグ以外のステートは設定されていません。

メンバー内容
leftCornerWidgetSize左コーナーウィジェットのQSize (もしあれば)。
右コーナーウィジェットサイズ右コーナーウィジェットのQSize (もしあれば)。
線幅パネルを描画する線幅を保持します。
midLineWithこの値は現在常に0です。
形状タブバーのタブの形。
タブバーサイズタブバーのQSize

スクロールバー

スクロールバーのスタイル構造です:

QScrollBar 単にスタイル・オプションを作成し、 を描画します。スタイルによっては、追加ページとサブページの背景を で描画したり、次行と前行のインジケータの矢印を描画するためにインジケータ矢印を使用します。これらの使用は個々のスタイルに任されているため、ツリーには含めていません。スタイルの は、スクロールバーの境界からマウスが移動してもハンドルが動く最大距離(ピクセル)です。CC_ScrollBar PE_PanelButtonBevel PM_MaximumDragDistance

以下は、Java スタイルのスクロールバーのイメージです:

スクロール・バーが Java のものとは少し異なり、2 つのライン・アップ・インジケータがあることにお気づきでしょう。これは、1つのサブコントロールに2つの別々の境界矩形を設定できることを示すためです。スクロール・バーは、完全にJavaスタイルで実装されたウィジェットの例です -QCommonStyle は描画に関与していません。

スクロール・バーがスタイル・オプションで設定できるさまざまな状態を見てみましょう:

状態設定される状態
State_Horizontalスクロール バーは水平です。

QScrollBar のスタイル・オプションはQStyleOptionSlider です。 そのメンバを次の表に示します。このオプションはすべてのQAbstractSliderで使われます。ここではスクロールバーに関連するメンバーについてのみ説明します。

メンバ内容
最大値スクロールバーの最大値。
最小値スクロールバーの最小値
ノッチターゲットノッチ間のピクセル数。
方向スクロールバーが垂直か水平かを指定するQt::Orientation enum の値。
ページステップページステップでスライダの値を増減させる数 (スライダのサイズと値の範囲に対する相対値)。
シングルステップ単一 (または行) ステップでスライダーの値を増減する数。
スライダ値スライダーの値。
sliderPositionスライダーハンドルの位置。スクロールバーがQAbstractSlider::tracking である場合、これはsliderValue と同じです。そうでない場合、マウスがハンドルを離す前にスクロールバーは値を更新しません。
upsideDownスクロールバーが値を増加させる方向を保持します。これは、すべての抽象スライダに対してQStyleOption::direction の代わりに使用されます。

スライダー

スライダーのサイズ ヒントを計算するとき、PM_SliderThicknessPM_SliderLength がスタイルからクエリされます。スクロール バーと同様に、QSlider は、マウスがスライダーの境界からPM_MaximumDragDistance 以内にある場合にのみ、ユーザーにハンドルを移動させます。自分自身を描画するときは、スタイル オプションを作成し、CC_SliderdrawComplexControl() を呼び出します:

Java スタイルのスライダーの画像も示します。すべての描画はCC_Slider で行われるので、サブ要素の境界矩形を示します。

QSlider すべての がそうであるように、 を使います。 に影響するメンバーを表に示します:QAbstractSlider QStyleOptionSlider QSlider

メンバー内容
最大値スライダーの最大値。
最小値スライダーの最小値
ノッチターゲット各ノッチ間のピクセル数。
方向スライダーが垂直か水平かを示すQt::Orientation enum値。
ページステップページステップでスライダーの値を増減させる数。
singleStep単一 (または行) ステップでスライダーの値を増減する数。
スライダ値スライダーの値。
sliderPositionスライダーの位置。スライダがtracking の場合、これはsliderValue と等しくなります。そうでない場合、スライダの値はハンドルがマウスで離されるまで変化しません。
upsideDownこのメンバは、すべての抽象スライダでQStyleOption::direction の代わりに使用されます。

スライダーは逆レイアウトのためにdirectionを使用しないことに注意する必要があります; それはupsideDown を使用します。

スピンボックス

QSpinBox が自身を描画するとき、QStyleOptionSpinBox を作成し、CC_SpinBox を描画するようスタイルに要求します。編集フィールドはスピンボックスの子であるライン編集です。フィールドの寸法は、スタイルがSC_SpinBoxEditField で計算します。

以下は、スピン ボックス用のスタイル ツリーです。スタイルがインジケーターの背景を描くためにボタン パネル プリミティブを使用する必要はありません。ツリーの下に、JavaスタイルのQSpinBox のサブ要素を示す画像があります。

QStyleOptionSpinBox は、スピン ボックス用のスタイル オプションです。これは、スピン ボックスに次の状態を設定できます:

状態設定される状態
State_SunkenサブコントロールCC_SpinUp またはCC_SpinDown のいずれかがマウスで押された場合に設定されます。

スピンボックスのスタイルオプションの残りのメンバは次のとおりです:

プロパティ機能
フレームスピンボックスがフレームを描画する場合、true
buttonSymbols上下ボタンのシンボルを決定するButtonSymbols列挙型の値。
stepEnabledスピンボックスのどのボタンが押下されているかを示すStepEnabled列挙型の値。

タイトルバー

タイトルバー複合コントロール(CC_TitleBar )は、QMdiArea の内部ウィンドウのタイトルバーを描画するために使用されます。通常、ウィンドウタイトル、閉じる、最小化、システムメニュー、最大化ボタンで構成されます。スタイルによっては、ウィンドウをシェーディングするためのボタンや、コンテキスト依存ヘルプのボタンもあります。

バーはサブ要素を使わずにCC_TitleBar で描かれます。ボタンをどのように描画するかは個々のスタイル次第ですが、スタイルが提供すべきボタンの標準ピクセルマップがあります。

Javaスタイルのタイトル・バーの上の画像では、Javaスタイルでサポートされるサブ要素(すべて標準のpixmapsで描画される)の境界矩形を示しています。ボタンの背景はPE_PanelButtonTool を使って描画するのが普通ですが、必須ではありません。

タイトル・バーのスタイル・オプションはQStyleOptionTitleBar です:

メンバ内容
アイコンタイトルバーのアイコン。
テキストタイトルバーのラベルのテキスト。
ウィンドウフラグQt::WindowFlag enum のフラグ。QMdiArea がウィンドウ管理に使用するウィンドウフラグです。
titleBarStateタイトルバーを含むウィンドウのQWidget::windowState() です。

コンボボックス

QComboBox は、CC_ComboBoxCE_ComboBoxLabel で、編集不可能なボックスのボタンとラベルを描画するスタイルを使用します。

ユーザーがコンボ ボックスをクリックしたときにポップアップ表示されるリストは、デリゲートによって描画されます。ただし、スタイルを使用して、サブ要素SC_ComboBoxListBoxPopup でリストのサイズと位置を制御できます。スタイルはまた、編集可能ボックスの編集フィールドの位置をSC_ComboBoxEditField で決定します。フィールド自体はQLineEdit で、コンボボックスの子要素です。

Javaスタイルのコンボ・ボックスのサブ要素とサブ要素の矩形をアウトライン化した画像を示します:

Javaのコンボボックスはフォーカス矩形を使いません。フォーカスがあると背景色が変わります。SC_ComboBoxEdit フィールドは、QComboBox が編集フィールドのサイズを計算するときにも、スタイルがコンボボックスのラベルのサイズを計算するときにも使用されます。

コンボボックスのスタイルオプションはQStyleOptionComboBox です:

状態設定時
State_Selectedボックスは編集可能ではなく、フォーカスがあります。
State_SunkenSC_ComboBoxArrow はアクティブです。
State_onボックスのコンテナ(リスト)が表示されている。

他のメンバのスタイル・オプションは次のとおりです:

メンバ内容
カレントアイコンコンボボックスの現在の(選択された)項目のアイコン。
カレントテキストコンボボックスの現在の項目のテキスト。
編集可能コンボボックスが編集可能かどうかを保持します。
フレームコンボボックスにフレームがあるかどうかを保持します。
アイコンサイズ現在のアイテムのアイコンのサイズ。
popupRectコンボボックスのポップアップリストの外接矩形。

グループボックス

サイズのヒントを計算するとき、QGroupBox はスタイルから3つのピクセル メトリックを取得します:PM_IndicatorWidth PM_CheckBoxLabelSpacing PM_IndicatorHeight QGroupBox のスタイル要素ツリーは次のとおりです:

Qt では、チェック・ボックスの描画方法に制限はありません。Java スタイルでは、CE_IndicatorCheckBox を使用して描画します。完全なツリーについては、チェック・ボタンとラジオ・ボタンを参照してください。

また、サブコントロールとサブコントロールの矩形が描画されたウィジェットの画像も示します:

グループボックスのスタイルオプションはQStyleOptionGroupBox です。以下の状態を設定できます:

状態Set When
State_Onチェックボックスがチェックされている。
State_Sunkenチェックボックスが押されている。
State_Offチェックボックスがチェックされていない(またはチェックボックスがない)。

QStyleOptionGroupBox

メンバー内容
特徴グループボックスのフレームを記述するQStyleOptionFrame::FrameFeatures enum のフラグ。
lineWidthパネルを描画する線幅。これは常に1である。
textグループボックスのテキスト。
テキスト配置グループボックスのタイトルの配置。
textColorテキストの色(QColor )。

スプリッター

スプリッタの構造は単純で、サブ要素を含まないので、スプリッタの画像は含めません。CE_Splitter は、他の要素やメトリクスを使用しません。

ス プ リ ッ タ のス タ イルオプシ ョ ンは、 ベース ク ラ スQStyleOption を用います。スプリッターには以下の状態フラグを設定できます:

状態Set When
State_Horizontal水平ス プ リ ッ タ ーであ る と き に設定。

QSplitter initFrom State_MouseOver と フラグを自分で設定します。State_Disabled

プログレス・バー

CE_ProgressBar 要素はQProgressBar で使用され、このウィジェットで使用される唯一の要素です。スタイル構造から始めます:

以下は、共通スタイルのプログレス・バーです(Javaスタイルの外接矩形は等しい):

QProgressBar のスタイル・オプションはQStyleOptionProgressBar です。このバーは状態フラグを設定しませんが、オプションの他のメンバは次のとおりです:

メンバ内容
最小値バーの最小値。
最大値バーの最大値。
プログレスバーの現在値。
テキスト配置ラベル内のテキストの整列方法。
textVisibleラベルを描画するかどうか。
テキストラベルのテキスト。
向きプログレスバーは垂直または水平にすることができます。
反転表示進行状況が反転している (つまり、横向きのバーでは右から左へ)。
bottomToToptrue 、垂直プログレスバーのラベルを90度回転させる。

ツールボタン

ツールボタンは独立して、あるいはツールバーの一部として存在します。どちらでも等しく描画されます。QToolButton は、CC_ToolButton という1つのスタイル要素だけを描画します。

以下は、ウィジェットのスタイル構造のツリーです:

PE_FrameButtonToolPE_IndicatorArrowDown は、Javaスタイルが描画するためツリーに含まれていますが、必要に応じて省略することができます。また、構造は異なっていてもかまいません。QCommonStyle例えば、PE_IndicatorButtonDropDownPE_IndicatorArrowDown の両方をCE_ToolButton の中に描画します。

また、サブ要素の境界矩形とサブコントロールをアウトライン化したツールボタンの画像もあります。

以下はツールボタンの状態表です:

状態設定時
State_AutoRiseツールボタンにautoRiseプロパティが設定されている。
State_Raisedボタンが沈んでいない(つまり、チェックされたり、マウスで押されたりしている)。
State_Sunkenボタンが下がっている。
State_Onボタンがチェック可能で、チェックされている。

QStyleOptionToolButton には以下のメンバも含まれます:

メンバ内容
arrowTypeボタンの矢印の方向(アイコンの代わりに矢印が使用される場合)を含むQt::ArrowType enum値。
特徴QStyleOptionToolButton::ButtonFeature 列挙型のフラグで、ボタンが矢印、メニュー、および/またはポップアップ遅延を持つかどうかを記述します。
フォントボタンラベルのQFont
アイコンツールボタンのQIcon
アイコンサイズボタンのアイコンのサイズ。
posQWidget::pos() で指定したボタンの位置。
テキストボタンのテキスト
toolButtonStyleボタンがアイコンを表示するか、テキストを表示するか、あるいはその両方を表示するかを決定するQt::ToolButtonStyle 列挙型の値。

ツールバー

ツールバーはmain window framework の一部であり、そのスタイルオプションを構築する間、属するQMainWindow と協調します。メインウィンドウには、ツールバーを置くことができる4つの領域があります。それらはウィンドウの4つの辺(すなわち、北、南、東、西)に隣接して配置される。各領域内には、複数のツールバーが並ぶことができます。1つの行は、同じ向き(垂直または水平)のツールバーが隣り合って配置されています。

Toolbars Qtのツールバーは3つの要素で構成されています:ツールバーとその内容の外接矩形(つまり、位置とサイズ)を計算するのはQMainWindowLayoutです。メイン・ウィンドウは、バーのサイズを計算するとき、ツールバーのアイテムの も使用します。CE_ToolBar PE_IndicatorToolBarHandle PE_IndicatorToolBarSeparator sizeHint()

以下は、QToolBar の要素ツリーです:

点線は、QToolBar が QToolBarLayout のインスタンスを保持し、QToolBarSeparators が QToolBarLayout によって保持されていることを示しています。ツールバーが浮いている(つまり、それ自身のウィンドウを持っている)場合、PE_FrameMenu 要素が描画されます。そうでない場合、QToolBarCE_ToolBar を描画します。

以下は、Javaスタイルのツールバーのイメージです:

QToolBarSaparatorは、スタイル・オプションにQStyleOption を使用します。QToolBarSaparatorは、そのスタイル・オプションにState_Horizontal 。それ以外は、initFrom ()を使用します。

QToolBar のスタイル・オプションはQStyleOptionToolBar です。バーが水平の場合(すなわち、北または南のツールバー領域にある場合)、(共通フラグ以外に)設定される唯一の状態フラグはState_Horizontal です。スタイルオプションのメンバ変数は以下のとおりです:

メンバ内容
特徴ToolBarFeature の値で、 バーが移動可能かど う かを保持 し ます。
lineWidthツールバーフレームの幅。
midLineWidthこの変数は現在使用されておらず、常に 0 です。
positionOfLineツールバー領域内のツールバーラインの位置。
positionWithinLineツールバーライン内のツールバーの位置。
ツールバーエリアツールバーが属するツールバーエリア。

Qt のメニューはQMenu で実装されています。QMenu はアクションのリストを保持し、それをメニュー・アイテムとして描画します。QMenu が paint イベントを受け取ると、各メニュー項目のサイズを計算し、CE_MenuItem で個別に描画します。メニュー項目はラベル(内容)のための独立した要素を持たないので、すべての描画はCE_MenuItem で行われます。また、メニューの枠はPE_FrameMenu で描画されます。スタイルがスクロールをサポートしている場合はCE_MenuScroller も描画されます。メニューが外接矩形に対して大きすぎる場合はCE_MenuTearOff が描画されます。

スタイル構造ツリーには、QMenu も含まれています。メニュー項目の外接矩形は、メニューのサイズのヒントと、メニューが表示またはサイズ変更されたときに計算されます。

CE_MenuScrollerCE_MenuTearOff 要素はQCommonStyle によって処理され、メニューが大きすぎて画面に収まらない場合以外は表示されません。PE_FrameMenu はポップアップメニューの場合のみ描画されます。

QMenu はそのアクションに基づいて矩形を計算し、スタイルがそれをサポートしていれば と を呼び出します。CE_MenuItem CE_MenuScroller

また、チェック可能なメニュー項目の描画にはPE_IndicatorCheckBoxPE_IndicatorMenuCheckMark を使用する代わりに)とPE_IndicatorRadioButton を使用するのが一般的です。これはオプションであり、スタイルによって異なるため、スタイルツリーには含めていません。

メニュー項目のスタイルオプションはQStyleOptionMenuItem です。以下の表は、その状態フラグとその他のメンバについて説明しています。

状態設定
State_Selectedマウスがアクションの上にあり、アクションがセパレーターでない。
State_Sunkenメニュー項目上でマウスが押し下げられたとき。
State_DownArrowメニューアイテムがメニュースクローラーであり、メニューを下方向にスクロールする場合に設定されます。
メンバー内容
チェックタイプCheckType enumの値で、NotCheckable、Exclusive、NonExclusiveのいずれか。
チェック済みメニュー項目がチェックされている場合、true
フォントメニュー項目のテキストに使用するQFont
アイコンメニュー項目のQIcon
maxIconWidthアイコンの最大幅。
menuHasCheckableItemsメニュー内の少なくとも1つの項目がチェック可能である場合にtrue
menuItemTypeメニュー項目のタイプ。これはMenuItemType の値です。
menuRectメニュー項目が存在するQMenu の外接矩形。
タブ幅メニュー項目のテキストとショートカットの間の距離。
テキストメニュー項目のテキスト。

CE_MenuTearOffCE_MenuScroller のスタイル・オプションのセットアップもQStyleOptionMenuItem を使用する。QStyleOptioninitFrom() と共通の設定に加えて、menuRect 変数を設定するだけである。

QMenuBar は、各メニューバー項目とメニューバーの空領域を描画するためにスタイルを使用します。プルダウン・メニューそのものは です(「QMenuメニュー」を参照)。メニュー バーのスタイル要素ツリーは次のとおりです:

パネルと空の領域はメニュー項目の後に描画されます。QMenuBar がスタイルに送信するQPainter には、アイテムの外接矩形がクリップされているので(つまり、クリップ領域)、アイテムの上に描画する心配はありません。QMenuBar のピクセル メトリックは、メニュー バー アイテムの境界矩形が計算されるときに使用されます。

QStyleOptionMenuItem はメニューバーアイテムに使用されます。 で使用されるメンバは次の表のとおりです:QMenuBar

メンバ内容
menuRectアイテムが属するメニューバー全体の外接矩形。
text項目のテキスト。
アイコンメニュー項目のアイコン (スタイルがこのアイコンを描画することは一般的ではありません)。

QStyleOptionMenuItem は の描画にも使われます。CE_EmptyMenuBarArea

QStyleOptionFrame はパネル枠の描画にも使われます。 は に設定される。 は現在常に 0 に設定される。lineWidth PM_MenuBarPanelWidth midLineWidth

アイテムビューヘッダー

Qt のアイテムビューのヘッダーを描画するスタイルです。アイテムビューは、個々のセクションの寸法を保持します。また、デリゲートはこのスタイルを使用して、アイテムの周りに装飾やフレームを描くことができます。QItemDelegate例えば、PE_FrameFocusRectPE_IndicatorItemViewItemCheck を描画します。

以下は、Javaヘッダーの外接矩形を示すQTableWidget です:

QHeaderView は、サイズとヒット・テストの計算にCT_HeaderSectionPM_HeaderMarginPM_HeaderGripMargin を使用します。PM_HeaderMarkSize は、現在 Qt では使用されていません。QTableView は、左上隅のボタン(つまり、縦と横のヘッダーが交差する領域)をCE_Header として描画します。

ヘッダービューのスタイルオプションはQStyleOptionHeader です。ビューは一度に1つのヘッダーセクションを描くので、データは描かれているセクションのものである。その内容は

メンバー内容
アイコンヘッダーのアイコン(描画中のセクションのもの)。
iconAlignmentヘッダー内のアイコンの配置 (Qt::Alignment)。
向きヘッダーがビューの上の水平ヘッダーであるか、左の垂直ヘッダーであるかを決定するQt::Orientation 値。
position他のセクションに対するヘッダーセクションの相対位置を指定するQStyleOptionHeader::SectionPosition 値。
セクション描画されるセクションを保持します。
selectedPosition描画されているセクションに対する、選択されたセクションの相対位置を指定するQStyleOptionHeader::SelectedPosition 値。
sortIndicatorセクションのソートインジケーターが描画される方向を表すQStyleOptionHeader::SortIndicator 値。
テキスト現在描画されているセクションのテキスト。
textAlignmentヘッダーセクション内のテキストのQt::Alignment

ツリーの分岐インジケーター

ツリービューのブランチインジケータは、PE_IndicatorBranch のスタイルで描画されます。ここでのインジケーターとは、ツリー内のノードの関係を表すインジケーターと考えます。一般的なQStyleOption は、これらの要素を描画するためのスタイルに送信されます。さまざまな枝のタイプはステートによって記述されます。特定のスタイル・オプションはないので、単に状態の表を示します:

状態設定
State_Siblingツリーのノードに兄弟がある(つまり、同じ列に別のノードがある)。
State_Itemこのブランチ・インジケータはアイテムを持っています。
State_Childrenブランチに子がある(つまり、ブランチで新しいサブツリーを開くことができる)。
State_Openこのブランチ・インジケータには、開かれたサブツリーがあります。

ツリー ビュー(およびツリー ウィジェット)は、このスタイルを使用してツリーのブランチ(ノード)を描画します。

QStyleOption は、 のスタイルとして使用され、ブランチのタイプに応じてステート フラグが設定されます。PE_IndicatorBranch

分岐インジケータにはツリー構造がないため、Java スタイルではツリーのイメージのみを表示します。各状態は、画像内で特定の色の長方形でマークされている(つまり、長方形は境界長方形ではない)。注意しなければならない状態の組み合わせは、すべて画像で表現されている。

ツールボックス

PM_SmallIconSize sizeHints 用のツールボックスです。

QToolBox は、ウィジェットのコレクションを保持するコンテナです。各ウィジェットに1つのタブがあり、一度に1つずつ表示されます。ツールボックスは、表示するコンポーネント(ツールボックスのボタンと選択したウィジェット)を にレイアウトします。 ツールボックスのスタイル ツリーは次のようになります:QVBoxLayout

Plastiqueスタイルのツールボックスの画像を示します:

すべての要素は、Plastique スタイルでも、他の組み込み Qt スタイルと同様に、同じ境界矩形を持っています。

ツールボックスのスタイルオプションはQStyleOptionToolBox で、ツールボックスの内容のテキストとアイコンが含まれます。QToolBox によって設定される唯一の状態は、State_Sunken で、ユーザーがマウスでタブを押したときに設定されます。QStyleOptionToolBox の残りのメンバーは以下のとおりです:

メンバ内容
アイコンツールボックスタブのアイコン。
テキストツールボックスタブのテキスト

サイズグリップ

サイズグリップは、サイズヒントをCT_SizeGrip で計算します。ピクセルメトリックPM_SizeGripSize は Qt では現在使われていません。QSizeGrip の Plastique スタイルの画像の要素ツリーを以下に示します:

QMainWindow の右下にサイズグリップを表示します。

サイズグリップスタイルオプションQStyleOptionSizeGrip には、QStyleOption の共通メンバ以外に 1 つのメンバがあります:

メンバ内容
コーナーグ リ ッ プがウ ィ ン ド ウ (ない し 同等物) 内の ど の隅にあ る か を記述す るQt::Corner 値。

ゴムバンド

QRubberBand のスタイル ツリーは 2 つのノードから構成されます。

QMdiArea で Java スタイルのウィンドウをゴムバンドで動かしているイメージを示します:

輪ゴムのスタイル オプションはQStyleOptionRubberBand です:

メンバー内容
不透明輪ゴムが不透明なスタイル(すなわち、色)で描画されなければならない場合にtrue となるブール値。
shape輪ゴムの形状を保持するQRubberBand::Shape enum 値(矩形または直線)。

ドックウィジェット

ドック ウィジェットがコンテンツをレイアウトするとき、これらのピクセル メトリックのスタイルを要求します:PM_DockWidgetSeparatorExtent PM_DockWidgetTitleBarButtonMargin PM_DockWidgetFrameWidth PM_DockWidgetTitleMarginまた、SE_DockWidgetCloseButtonSE_DockWidgetFloatButton を使用して、float と close ボタンの外接矩形を計算します。

点線は、送信側が矢印の受信側のインスタンスを保持していることを示しています(つまり、描画するスタイル要素ではありません)。ドック ウィジェットは、メイン ウィンドウから切り離されているとき(つまり、トップ レベル ウィンドウであるとき)にのみPE_frameDockWidget を描画します。ドッキングされている場合は、インジケータ ドック ウィジェットのサイズ変更ハンドルを描画します。ドッキング状態でもフローティング状態でも、ドック・ウィジェットをプラスティック・スタイルで表示します:

スタイル・オプションはQStyleOptionDockWidget

メンバーコンテンツ
クローズ可能ドックウィンドウを閉じることができるかどうかを保持するブール値。
フロート可能ドックウィンドウが浮く(つまり、ドックウィンドウがあるメインウィンドウから離れる)ことができるかどうかを保持するブール値。
可動ドックウィンドウが移動可能かどうか(他のドックウィジェットエリアに移動できるかどうか)を保持するブール値。
タイトルドックウィンドウのタイトルテキスト。

ボタンにはQStyleOptionButton が使われます(内容の説明はツールボタンを参照してください)。ドックウィジェットのサイズ変更ハンドルには、プレーンな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.