スタイルによるウィジェットの描画方法
QStyle API には、ウィジェットを描画する関数、スライダーハンドルの位置計算など、一般的かつ困難なタスクのための静的ヘルパー関数、そしてウィジェットが描画中に必要とする計算(例えば、サイズヒントの算出など)を行う関数の3種類があります。 また、スタイルは一部のウィジェットのコンテンツのレイアウトを支援し、ウィジェットが使用するQPalette を調整することもできます。
このページでは、スタイルの実装で使用される構成要素について説明します。「ウィジェット・スタイル・リファレンス」には、各ウィジェットがどの構成要素を使用しているかが記載されています。
スタイル要素
QStyle は、グラフィカル要素を描画します。要素とは、ウィジェット、またはプッシュボタンのベベル、ウィンドウフレーム、スクロールバーなどのウィジェットの一部を指します。ほとんどの描画関数は 4 つの引数を取ります:
- 描画するグラフィカル要素を指定する列挙型値。
- その要素をどのように、どこにレンダリングするかを指定するQStyleOption 。
- 要素を描画するためのQPainter 。
- 描画が行われるQWidget 。この引数は省略可能です。
ウィジェットがスタイルに対して要素の描画を依頼する際、スタイルにはQStyleOption (描画に必要な情報を含むクラス)が渡されます。この にはスタイルが必要とするすべての情報が含まれているため、スタイルはウィジェットのコードを一切参照することなくウィジェットを描画できます。コンボボックスは、QComboBox だけでなく、任意のペイントデバイス上に描画することができます。
ウィジェットが最後の引数として渡されるのは、macOS上のアニメーション付きデフォルトボタンなどの特殊効果のためにスタイルがそれを必要とする場合を想定しているためですが、スタイルはこれに依存することはできません。複数の要素を自身で描画するウィジェットは自身を渡し、QStylePainter も同様に自身を渡します。ペイントデバイス上に直接描画するコードは、nullptr を渡す場合があります。
ウィジェットは、スタイル要素の階層(ツリー)で構成されています。たとえば、スタイルがプッシュボタンの描画要求を受け取ると、ラベル(テキストとアイコン)、ボタンのベベル、およびフォーカスフレームを描画します。 ボタンのベベルは、さらにベベルとパネルを囲むフレームで構成されています。以下の概念的なツリーは、プッシュボタンの要素を描画順に示しており、ネストされた要素はそれより上位の要素によって描画されます:
- プッシュボタン
- ボタンのベベル
- デフォルトのボタンフレーム
- ボタンパネル
- ラベル(アイコンとテキスト)
- フォーカス枠
- ボタンのベベル
リファレンス内のプッシュボタンには、QPushButton の実際のツリーが要素名とともに表示されています。
ウィジェットは、必ずしもスタイルに対して1つの要素のみを描画するよう要求するわけではありません。ウィジェットは、異なる要素を描画するためにスタイルに対して複数回呼び出しを行うことがあります。その一例がQTabWidget であり、このウィジェットはタブとフレームを個別に描画します。
要素には、プリミティブ要素、コントロール要素、複合コントロール要素の3種類があります。これらは、PrimitiveElement 、ControlElement 、ComplexControl の各列挙型で定義されています。各列挙型の値には、そのタイプを識別する接頭辞が付いています。プリミティブ要素はPE_ 、コントロール要素はCE_ 、複合コントロール要素はCC_ です。QStyle クラスのドキュメントには、これらの要素と、ウィジェットのスタイリングにおけるそれぞれの役割が記載されています。
プリミティブ要素
プリミティブ要素とは、一般的であり、複数のウィジェットで頻繁に使用されるGUI要素のことです。例としては、フレーム、ボタンのベベル、スピンボックス、スクロールバー、コンボボックス用の矢印などが挙げられます。 プリミティブ要素は単独では存在できず、常に大きな構造の一部となります。これらはユーザーとの対話には関与せず、GUI における受動的な装飾要素です。
コントロール要素
コントロール要素は、アクションを実行したり、ユーザーに情報を表示したりします。コントロール要素の例としては、プッシュボタン、チェックボックス、およびテーブルやツリービューのヘッダーセクションなどが挙げられます。 コントロール要素は、必ずしもプッシュボタンのような完全なウィジェットであるとは限らず、タブバーのタブやスクロールバーのスライダーといったウィジェットの一部である場合もあります。コントロール要素は、受動的ではないという点でプリミティブ要素とは異なります。つまり、ユーザーとの対話に関与するのです。
複数の要素で構成されるコントロールでは、要素のバウンディング矩形を計算するために `style` が使用されることがよくあります。SubElement 列挙型は、使用可能なサブ要素を定義します。この列挙型は、バウンディング矩形の計算にのみ使用されます。サブ要素は、プリミティブ要素、コントロール要素、複合要素のように描画されるグラフィカルな要素ではありません。
複合コントロール要素
複合コントロール要素にはサブコントロールが含まれています。複合コントロールは、ユーザーがマウスで操作する位置や押されるキーボードキーによって、異なる動作をします。これは、マウスがどのサブコントロール(存在する場合)の上に置かれているか、またはどのサブコントロールが押されているかによって決まります。 複合コントロールには、スクロールバーやコンボボックスなどがあります。スクロールバーでは、マウスを使ってスライダーを移動させたり、上矢印ボタンや下矢印ボタンを押したりすることができます。SubControl 列挙型は、利用可能なサブコントロールを定義します。
描画に加えて、このスタイルは、ユーザーがどのサブコントロール(存在する場合)を押したかをウィジェットに伝えます。たとえば、QScrollBar は、ユーザーがスライダー、スライダーの溝、またはボタンのいずれかを押したかを把握する必要があります。
サブコントロールは、制御要素とは異なります。スタイルを使用してサブコントロールを描画することはできません。スタイルは、サブコントロールが描画されるべき境界矩形を計算するだけです。ただし、複雑な要素では、制御要素やプリミティブ要素を使用してサブコントロールを描画するのが一般的です。 Qtの組み込みスタイルでは、この手法が頻繁に用いられています。例えば、QCommonStyle は、PE_IndicatorCheckBox を使用して、グループボックス内のチェックボックスを描画します。これはCC_GroupBox のサブコントロールです。一部のサブコントロールには、それに対応する制御要素があります。例えば、スクロールバーのスライダー(SC_ScrollBarSlider およびCE_ScrollBarSlider )などです。
サブ要素、サブコントロール、およびピクセルメトリック
スタイル要素およびウィジェットは、スタイルを使用してサブ要素やサブコントロールのバウンディング矩形を計算します。ピクセルメトリック(画面ピクセル単位でスタイルに依存するサイズ)も、描画時の測定に使用されます。QStyle 内の3つの列挙型(SubElement 、SubControl 、PixelMetric )は、利用可能な矩形とピクセルメトリックを表しています。それらの値は、SE_ 、SC_ 、PM_ で始まります。
スタイルのヒント
このスタイルは、StyleHint 列挙型の値で表される一連のスタイルヒントにも対応しています。ウィジェットによって、異なるスタイルでの機能や外観が異なる場合があります。 たとえば、メニューの項目が画面上の 1 列に収まらない場合、スクロールをサポートするスタイルもあれば、すべての項目を収めるために複数列で表示するスタイルもあります。ウィジェットは、styleHint() を使用してヒントを照会します。
標準アイコン
スタイルには通常、メッセージボックス、ファイルダイアログ、タイトルバーのボタン用に、警告、質問、エラーなどの画像を含む一連の標準アイコンが用意されています。これらはStandardPixmap 列挙型で名前が指定されており、standardIcon()は指定された値に対応するQIcon を返します。Qt Widgetsはこれらのアイコンを使用するため、スタイルを実装する際にはこれらを用意してください。
レイアウトの余白
スタイルは、レイアウト内のウィジェット間の間隔を計算します。この計算には 2 つの方法があります。 `PM_LayoutHorizontalSpacing ` および `PM_LayoutVerticalSpacing` に対して、`pixelMetric()` から間隔を返す方法があります(QCommonStyle ではこの方法を採用しています)。あるいは、より詳細な制御が必要な場合は、`layoutSpacing()` を再実装することもできます。この関数内では、隣接する 2 つのウィジェットのコントロールタイプ(QSizePolicy::ControlType )、サイズポリシー(QSizePolicy::Policy )、および対象のウィジェットのスタイルオプションに基づいて間隔を計算できます。
スタイルオプション
QStyleOption のサブクラスには、個々の要素のスタイルを設定するために必要なすべての情報が含まれています。QStyle 関数の呼び出し元は、通常スタック上でスタイルオプションをインスタンス化し、その内容を設定します。描画対象に応じて、各スタイルは異なるスタイルオプションクラスを期待します。例えば、PE_FrameFocusRect 要素はQStyleOptionFocusRect 引数を期待します。 また、カスタムスタイルで使用するための独自のサブクラスを作成することも可能です。パフォーマンス上の理由から、スタイルオプションはパブリック変数を保持しています。
ウィジェットは、State 列挙型によって定義されるさまざまな状態をとることができます。状態フラグの中には、ウィジェットによって意味が異なるものもありますが、State_Enabled のようにすべてのウィジェットに共通のものもあります。QStyleOption::initFrom()は共通の状態を設定し、残りの状態は個々のウィジェットが設定します。
特に注目すべきは、スタイルオプションには、描画されるウィジェットのパレットと境界矩形が含まれている点です。ほとんどのウィジェットには、専用のスタイルオプションがあります。たとえば、QPushButton やQCheckBox は、テキスト、アイコン、およびアイコンのサイズを含むQStyleOptionButton を使用します。各オプションの正確な内容については、『ウィジェット・スタイル・リファレンス』で説明されています。
`QStyle `関数で`QStyleOption `パラメータを受け取る場合、そのオプションを`QStyleOptionFocusRect`などのサブクラスにキャストする必要があることがよくあります。ポインタの型が正しいことを確認するには、`qstyleoption_cast()`を使用してください。オブジェクトが正しい型でない場合、`qstyleoption_cast()`はnullptr を返します:
const QStyleOptionFocusRect *focusRectOption =
qstyleoption_cast<const QStyleOptionFocusRect *>(option);
if (focusRectOption) {
//...
}一般的な状態フラグとメンバ
一部のステートや変数は、すべてのウィジェットに共通しています。ウィジェットは、QStyleOption::initFrom() を使用してこれらを設定します。すべての要素がこの関数を使用するわけではありません。ウィジェットがスタイルオプションを作成し、一部の要素ではinitFrom() からの情報は必要ありません。
| 状態 | 設定されるタイミング |
|---|---|
State_Enabled | ウィジェットが無効化されていないとき(QWidget::isEnabled() を参照)。 |
State_HasFocus | ウィジェットにフォーカスがある場合(QWidget::hasFocus() を参照)。 |
State_KeyboardFocusChange | ユーザーがキーボードを使用してフォーカスを変更したとき(WA_KeyboardFocusChange を参照)。 |
State_MouseOver | マウスカーソルがウィジェットの上にあるとき。 |
State_Active | ウィジェットがアクティブなウィンドウの子である場合。 |
その他の一般的なメンバは以下の通りです:
| メンバ | 説明 |
|---|---|
| rect | 描画対象の要素の境界矩形。initFrom() は、これをウィジェットの境界矩形(QWidget::rect())に設定します。 |
| direction | レイアウトの方向。Qt::LayoutDirection 列挙型の値です。 |
| palette | 要素の描画時に使用するQPalette 。initFrom() は、これをウィジェットのパレット(QWidget::palette())に設定します。 |
| fontMetrics | ウィジェット上にテキストを描画する際に使用するQFontMetrics 。 は、これをウィジェットのパレット( ())に設定します。 |
| styleObject | このオプションが記述するオブジェクト。通常はウィジェットです。スタイルは、アニメーションの状態を格納するためにこれを使用します。 |
QStyleOptionComplex を継承するクラスである複合スタイルオプションは、subControls とactiveSubControls という2つの変数をさらに共有しています。これらはいずれも、QStyle::SubControl 値のOR結合です。これらは、複合コントロールがどのサブコントロールで構成されており、そのうちのどれが現在アクティブであるかを示します。
QStyleの関数
QStyle には、プリミティブ要素、コントロール要素、および複合要素を描画するための 3 つの関数が定義されています:drawPrimitive()、drawControl()、およびdrawComplexControl() です。これらは、「スタイル要素」の項に記載されている引数を受け取ります。
すべてのウィジェットが自身のポインタを渡すわけではありません。関数に渡されたスタイルオプションに必要な情報が含まれていない場合は、ウィジェットの実装を確認して、自身が渡されているかどうかを確認してください。
QStyle また、要素を描画するためのヘルパー関数も提供されています。drawItemText() は、QPalette をパラメータとして受け取り、指定された矩形内にテキストを描画します。drawItemPixmap() は、指定された境界矩形内にピクマップを配置します。
その他の `QStyle ` 関数は、描画関数のための計算を行います。ウィジェットも、複数のスタイル要素を自ら描画する際に、サイズヒントや境界矩形を計算するためにこれらを使用します。これらの関数は通常、描画関数と同じ引数を受け取ります。
- subElementRect() は `SubElement ` 値を受け取り、サブ要素の境界矩形を計算します。スタイルはこの関数を使用して、要素の各部分をどこに描画すべきかを判断します。新しいスタイルを作成する場合、基底クラスのサブ要素の位置情報を再利用できます。
- subControlRect() は、複雑なコントロール内のサブコントロールの境界矩形を計算します。新しいスタイルを実装する際は、基底クラスと異なる矩形について、この関数を再実装してください。
- pixelMetric() は、画面ピクセル単位で表されるスタイル依存のサイズであるピクセルメトリックを返します。この関数は、PixelMetric 列挙型の値を引数として受け取ります。ピクセルメトリックは必ずしも静的な測定値である必要はなく、スタイルオプションから計算することもできます。
- sizeFromContents() は、指定されたコンテンツサイズに対するウィジェットのサイズを返します。ウィジェットはこれを使用して、自身のサイズヒントを計算します。
- hitTestComplexControl() は、複合コントロール内でマウスポインタが位置しているサブコントロールを返します。通常、これはsubControlRect() を使用してサブコントロールの境界矩形を取得し、カーソルの位置を含むものを特定することで行われます。
QStyle また、polish() およびunpolish() 関数も用意されています。Qt は、ウィジェットが最初に表示される前、およびスタイルが変更された際に、そのウィジェットの「ポリッシュ」処理を行い、スタイルが変更されたときやウィジェットが破棄された際には「ポリッシュ解除」を行います。これらの関数を使用して、ウィジェットに属性を設定したり、スタイルで必要とされるその他の処理を行ったりします。 たとえば、マウスがウィジェットの上にホバーしているタイミングを把握する必要がある場合は、polish() 内でWA_Hover ウィジェット属性を設定します。これにより、ウィジェットはスタイルオプション内でState_MouseOver を設定します。また、polish() のオーバーロードを使用することで、スタイルはQApplication を準備したり、アプリケーションパレットを調整したりすることもできます。詳細は「パレット」を参照してください。
最後に、QStyle には、一般的かつ困難なタスクのための静的ヘルパー関数が用意されています。sliderPositionFromValue() およびsliderValueFromPosition() は、スライダーの値とピクセル位置の変換を行います。visualRect()、visualPos()、およびvisualAlignment() は、論理座標と配置を、右から左へのレイアウトにおける対称的な位置に変換し、alignedRect() は、現在の方向に合わせて矩形を配置します。詳細については、QStyle クラスのドキュメントにある「Right-to-Left Desktops 」を参照してください。
QStyle の仮想関数を再実装する際は、基底クラスと異なる要素を処理し、それ以外のすべてについては基底クラスの実装を呼び出してください。
パレット
各スタイルは、QPalette によって提供されるブラシのパレットを使用して描画を行います。ウィジェットの状態ごとに 1 セットの色(QPalette::ColorGroup )が用意されています。具体的には、キーボードフォーカスを有するウィンドウ内のウィジェットには「active」、他のウィンドウ内のウィジェットには「inactive」、無効化されたウィジェットには「disabled」が割り当てられます。State_Active およびState_Enabled 状態フラグによって、どのグループを使用すべきかが指定されます。各グループには、QPalette::ColorRole で定義されたカラーロールが含まれています。 これらの役割は、ウィジェットの背景、テキスト、ボタンなどの描画など、色が適用される状況を記述しています。
各スタイルは、これらのカラーロールの使用方法を決定します。例えば、スタイルがグラデーションを使用する場合、パレットの色を取り込み、QColor::darker() やQColor::lighter() を使ってその色を暗くしたり明るくしたりすることで、グラデーションを作成できます。一般的に、パレットが提供していないブラシが必要な場合は、パレットが提供しているブラシから派生させて作成します。
アプリケーションにスタイルを設定すると、QtはスタイルのstandardPalette()からアプリケーションパレットを構築し、プラットフォームのテーマが提供するロールを上書きできるようにし、その結果をQStyle::polish()に渡します。そのオーバーロードを再実装して、スタイルに必要な色を調整してください。Qtは、アプリケーションがQApplication::setPalette()で明示的に設定したパレットを上書きすることはありません。
色をハードコーディングしないでください。アプリケーションや個々のウィジェットは独自のパレットを設定でき、そのパレットから色を抽出するスタイルはそれらに従います。また、追加のコードを一切書かずに、2つのパレットから明るいバリエーションと暗いバリエーションを取得することもできます。QtのFusionスタイルは次のように動作します:
|
|
スタイルは、考えられるすべてのパレットで美しく見える必要はありませんが、与えられたパレットを尊重する必要があります。
アイテムビュー
デリゲートは、アイテムビュー内のアイテムを描画します。 QtのデフォルトデリゲートであるQStyledItemDelegate は、CE_ItemViewItem を描画し、CT_ItemViewItem を使用して項目のサイズを計算します。したがって、スタイルは、付随するデリゲートがなくても項目の外観を制御できます。スタイルは、アイテムビューのヘッダー、ツリーブランチインジケータ、および行の背景を直接描画します。新しいデータ型やアイテムデータロールをサポートするには、カスタムデリゲートが必要です。「モデル/ビュープログラミング」を参照してください。
実装に関するアドバイス
スタイルを実装する際は、ウィジェットおよび基底クラスのコードをよく読んでください。ウィジェットによってスタイルの使用方法は異なり、基底クラスの実装は描画の状態に影響を与える可能性があります。例えば、QPainter の状態を復元せずに変更したり、適切なピクセルメトリクスやサブ要素を使用せずに一部の要素を描画したりする場合などです。
sizeFromContents() でのウィジェットの提案サイズを、必要がない限り変更しないでください。QCommonStyle の実装に任せてください。変更を加える場合は、最小限に留めてください。スタイル間でウィジェットのレイアウトが大きく異なると、アプリケーション開発が困難になります。
-reverse コマンドラインオプション、またはQGuiApplication::setLayoutDirection() を使用してスタイルをテストし、右から左へのレイアウトでも非対称な要素が正しく表示されることを確認してください。
関連項目: QStyle 、QStyleOption 、QStylePainter 、ウィジェット・スタイル・リファレンス、および「チェックボックスのスタイル設定:実践ガイド」。
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.

