スタイルシートの構文

Qt スタイルシートの用語と構文規則は、HTML CSS とほとんど同じです。すでに CSS をご存知の方は、このセクションをさっと読み進めることができるでしょう。

スタイルの規則

スタイル・シートは、一連のスタイル・ルールで構成されます。スタイル・ルールは、セレクタと宣言で構成されます。セレクタは、ルールの影響を受けるウィジェットを指定し、宣言は、ウィジェットに設定されるべきプロパティを指定します。例えば

QPushButton { color: red }

上記のスタイル・ルールでは、QPushButton がセレクタ、{ color: red } が宣言です。このルールでは、QPushButton とそのサブクラス(例えば、MyPushButton )は、前景色として赤を使用することが指定されています。

Qtスタイルシートでは、一般的に大文字と小文字を区別しません(つまり、colorColorCOLORcOloR は同じプロパティを参照します)。唯一の例外はクラス名、object names 、Qtプロパティ名で、これらは大文字と小文字を区別します。

カンマ (,) でセレクタを区切ることで、同じ宣言に対して複数のセレクタを指定することができます。例えば

は、この 3 つのルールのシーケンスに相当します:

QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }

スタイル・ルールの宣言部分は、中括弧 ( ) で囲まれた property: valueペアのリストで、中括弧 ({}) で囲み、セミコロンで区切ります。例えば

QPushButton { color: red; background-color: white }

Qtウィジェットが提供するプロパティのリストについては、以下の「プロパティのリスト」のセクションを参照してください。

セレクタの種類

これまでの例では、最も単純なセレクタであるタイプ・セレクタを使用しました。Qtスタイルシートは、CSS2で定義されているすべてのセレクタをサポートしています。下の表は、最も便利なセレクタの種類をまとめたものです。

セレクタ説明
ユニバーサル・セレクタ*すべてのウィジェットにマッチします。
タイプセレクタQPushButtonQPushButton およびそのサブクラスのインスタンスにマッチします。
プロパティ セレクタQPushButton[flat="false"]flat でないQPushButton のインスタンスにマッチします。このセレクタを使用して、QVariant::toString() をサポートしている Qtプロパティをテストすることができます(詳細については、toString() 関数のドキュメントを参照してください)。さらに、特別なclass プロパティも、クラスの名前に対してサポートされています。

このセレクタは、動的プロパティのテストにも使用できます。ダイナミック・プロパティを使用したカスタマイズの詳細については、「ダイナミック・プロパティを使用したカスタマイズ」を参照してください。

= の代わりに、~= を使用して、QStringList タイプの Qt プロパティが、指定されたQString を含むかどうかをテストすることもできます。

警告: 警告: スタイル・シートが設定された後に Qt プロパティの値が変更された場合、スタイル・シートの再計算が必要になることがあります。これを実現する1つの方法は、スタイル・シートの設定を解除し、再度設定することです。

クラス・セレクタ.QPushButtonQPushButton のインスタンスにマッチしますが、そのサブクラスにはマッチしません。

これは*[class~="QPushButton"] と同等です。

ID セレクタQPushButton#okButtonobject nameokButton であるすべてのQPushButton インスタンスにマッチします。
子孫セレクタQDialog QPushButtonQDialog の子孫(子、孫など)であるQPushButton のすべてのインスタンスにマッチします。
子セレクタQDialog > QPushButtonQDialog の直接の子であるQPushButton のすべてのインスタンスにマッチします。

サブコントロール

複雑なウィジェットをスタイリングする場合、QComboBox のドロップダウン・ボタンやQSpinBox の上下矢印など、ウィジェットのサブコントロールにアクセスする必要があります。セレクタは、特定のウィジェットのサブコントロールにルールの適用を制限できるサブコントロールを含むことができます。例えば

QComboBox::drop-down { image: url(dropdown.png) }

上記のルールは、すべてのQComboBoxのドロップダウン・ボタンにスタイルを設定する。ダブルコロン (::) 構文は CSS3 擬似要素を連想させますが、Qt サブコントロールは概念的にこれらとは異なり、異なるカスケード・セマンティクスを持っています。

サブコントロールは、常に別の要素(参照要素)に対して配置されます。この参照要素は、ウィジェットであったり、別のサブコントロールであったりします。例えば、QComboBox::drop-downは、デフォルトでは、QComboBox のPadding長方形の右上隅に配置されます。::drop-downは、デフォルトでは、::drop-downサブコントロールのContents長方形の中央に配置されます。ウィジェットのスタイル設定に使用するサブコントロールとそのデフォルト位置については、以下の「スタイル設定可能なウィジェットのリスト」を参照してください。

使用する原点矩形は、subcontrol-originプロパティを使用して変更できます。例えば、ドロップダウンをデフォルトのパディング矩形ではなく、QComboBox のマージン矩形に配置したい場合は、次のように指定します:

QComboBox {
    margin-right: 20px;
}
QComboBox::drop-down {
    subcontrol-origin: margin;
}

マージン矩形内のドロップダウンの配置は、subcontrol-positionプロパティを使用して変更します。

widthプロパティとheightプロパティを使用して、サブコントロールのサイズを制御することができます。画像を設定すると、暗黙的にサブコントロールのサイズが設定されることに注意してください。

相対位置指定(position: relative)では、サブコントロールの位置を初期位置からオフセットすることができます。例えば、QComboBox のドロップダウンボタンが押されたとき、中の矢印をオフセットして「押された」効果を与えたい場合があります。これを実現するには、次のように指定します:

QComboBox::down-arrow {
    image: url(down_arrow.png);
}
QComboBox::down-arrow:pressed {
    position: relative;
    top: 1px; left: 1px;
}

絶対位置指定スキーム(position: absolute)では、サブコントロールの位置とサイズを参照要素に対して変更することができます。

一旦位置決めされると、ウィジェットと同じように扱われ、ボックス・モデルを使用してスタイルを設定することができます。

サポートされているサブコントロールのリストについては、下の「サブコントロールのリスト」を、実際の例については、「QPushButtonのメニュー・インジケータ・サブコントロールをカスタマイズする」を参照してください。

注意: QComboBoxQScrollBar のような複雑なウィジェットでは、1つのプロパティやサブコントロールをカスタマイズすると、他のすべてのプロパティやサブコントロールもカスタマイズする必要があります。

擬似状態

セレクタは、ウィジェットの状態に基づいてルールの適用を制限する擬似状態を含むことができます。擬似状態は、セレクタの末尾にコロン(:)を挟んで表示されます。例えば、次のルールは、マウスがQPushButton の上にあるときに適用されます:

QPushButton:hover { color: white }

擬似状態は、感嘆符演算子を使って否定することができます。例えば、マウスがQRadioButton の上にない場合、以下のルールが適用されます:

QRadioButton:!hover { color: red }

擬似状態は連鎖させることができ、その場合は論理 AND が暗示されます。た と えば、 チ ェ ッ ク さ れたQCheckBox の上にマ ウ ス を置 く と 、 以下の規則が適用 さ れます:

QCheckBox:hover:checked { color: white }

否定された擬似状態は擬似状態の連鎖の中に現れることがある。例えば、以下のルールは、押されていないQPushButton の上にマウスが置かれたときに適用されます:

QPushButton:hover:!pressed { color: blue; }

必要であれば、カンマ演算子を使って論理和を表現することもできる:

QCheckBox:hover, QCheckBox:checked { color: white }

擬似状態は、サブコントロールと組み合わせて表示することができます。例えば

QComboBox::drop-down:hover { image: url(dropdown_bright.png) }

Qt ウィジェットが提供する擬似状態のリストについては、「擬似状態のリスト」のセクションを参照してください。

競合の解決

複数のスタイル・ルールが同じプロパティを異なる値で指定すると、競合が発生します。次のスタイル シートを考えてみましょう:

QPushButton#okButton { color: gray }
QPushButton { color: red }

両方のルールがokButton というQPushButton インスタンスに一致し、color プロパティに競合があります。この衝突を解決するには、セレクタの特異性を考慮する必要があります。上の例では、QPushButton#okButtonQPushButton よりも特定性が高いと考えられます。なぜなら、 は(通常)クラスのすべてのインスタンスではなく、単一のオブジェクトを参照するからです。

同様に、擬似状態を持つセレクタは、擬似状態を指定しないセレクタよりも具体的です。従って、次のスタイル・シートは、QPushButton 、マウスがマウス・オーバーした時に白いテキストを表示し、そうでなければ赤いテキストを表示するように指定します:

QPushButton:hover { color: white }
QPushButton { color: red }

ここがやっかいなところです:

QPushButton:hover { color: white }
QPushButton:enabled { color: red }

ここでは、両方のセレクタが同じ特異性を持っているので、ボタンが有効になっている間にマウスがボタンの上に置かれると、2番目のルールが優先されます。この場合、テキストを白にしたいのであれば、このようにルールを並べ替えることができる:

QPushButton:enabled { color: red }
QPushButton:hover { color: white }

あるいは、最初のルールをより具体的にすることもできる:

QPushButton:hover:enabled { color: white }
QPushButton:enabled { color: red }

同じような問題がタイプ・セレクタでも発生する。次の例を考えてみよう:

QPushButton { color: red }
QAbstractButton { color: gray }

両方のルールがQPushButton インスタンスに適用され(QPushButtonQAbstractButton を継承するので)、colorプロパティで競合が発生します。QPushButtonQAbstractButton を継承しているため、QPushButton の方がQAbstractButton より具体的であると考えたくなるかもしれません。しかし、スタイル・シートの計算では、すべてのタイプ・セレクタは同じ具体性を持ち、最後に現れるルールが優先されます。言い換えれば、QPushButtonを含むすべてのQAbstractButtonについて、color は gray に設定されます。もし本当にQPushButtonのテキストを赤にしたいのであれば、いつでもルールを並べ替えることができます。

ルールの特異性を決定するために、QtスタイルシートはCSS2仕様に従っています:

セレクタの特異性は以下のように計算されます:

  • セレクタ内のID属性の数を数える (= a)
  • セレクタ内の他の属性や擬似クラスの数を数える(= b)
  • セレクタ内の要素名の数を数える (= c)
  • 擬似要素[つまりサブコントロール]は無視する。

a-b-cの3つの数字を(大きな基数を持つ数体系で)連結することで、特異性が得られます。

いくつかの例を挙げよう:

*             {}  /* a=0 b=0 c=0 -> specificity =   0 */
LI            {}  /* a=0 b=0 c=1 -> specificity =   1 */
UL LI         {}  /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LI      {}  /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]{}  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red  {}  /* a=0 b=1 c=3 -> specificity =  13 */
LI.red.level  {}  /* a=0 b=2 c=1 -> specificity =  21 */
#x34y         {}  /* a=1 b=0 c=0 -> specificity = 100 */

カスケーディング

スタイル・シートは、QApplication 、親ウィジェット、子ウィジェットに設定できます。任意のウィジェットの有効スタイル・シートは、ウィジェットの祖先(親、祖父母など)に設定されたスタイル・シートと、QApplication に設定されたスタイル・シートをマージして得られます。

競合が発生した場合、競合するルールの特異性に関係なく、ウィジェット自身のスタイル・シートは、継承されたスタイル・シートよりも常に優先されます。同様に、親ウィジェットのスタイル・シートは、祖父母のスタイル・シートより優先されます。

この結果、ウィジェットにスタイル規則を設定すると、自動的に、祖先ウィジェットのスタイル・シートやQApplication スタイル・シートで指定された他の規則よりも優先されます。次の例を考えてみましょう。まず、QApplication にスタイル・シートを設定します:

qApp->setStyleSheet("QPushButton { color: white }");

次に、QPushButton オブジェクトにスタイル・シートを設定します:

myPushButton->setStyleSheet("* { color: blue }");

QPushButton のスタイル・シートは、アプリケーション全体のスタイル・シートによって提供されるより具体的なルール・セットにもかかわらず、QPushButton (および任意の子ウィジェット)に青いテキストを強制します。

と書いても結果は同じだったでしょう。

myPushButton->setStyleSheet("color: blue");

ただし、QPushButton に子ウィジェットがあった場合(ありえませんが)、スタイル・シートは子ウィジェットには影響しません。

スタイル・シートのカスケーディングは複雑なトピックです。詳細については、CSS2 仕様書を参照してください。Qtは現在、!important を実装していません。

継承

古典的な CSS では、項目のフォントや色が明示的に設定されていない場合、自動的に親から継承されます。デフォルトでは、Qt Style Sheets を使用している場合、ウィジェットは親ウィジェットからフォントと色の設定を自動的に継承しません

例えば、QGroupBox の中にQPushButton があるとします:

qApp->setStyleSheet("QGroupBox { color: red; } ");

QPushButton には明示的な色設定がありません。したがって,親ウィジェットQGroupBox の色を継承する代わりに,システム・カラーを持ちます.QGroupBox とその子に色を設定したい場合は、次のように書けばよい:

qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");

一方、QWidget::setFont() とQWidget::setPalette() を使ってフォントとパレットを設定すると、子ウィジェットに伝搬します。

フォントとパレットが子ウィジェットに伝搬することを望むなら、次のようにQt::AA_UseStyleSheetPropagationInWidgetStyles フラグを設定します:

使用方法

QCoreApplication::setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles, true);

ウィジェットスタイルのフォントとパレットの伝搬を有効にすると、Qt スタイルシートによって行われたフォントとパレットの変更は、スタイルシートによってターゲットにされたすべての QWidgets 上で、対応するQWidget::setPalette() とQWidget::setFont() メソッドをユーザーが手動で呼び出したかのように動作します。

  • スタイルシートによる変更は伝搬されます。変更が行われた時点で、スタイル・シートに一致するすべてのウィジェットに一度だけプッシュされます。
  • QWidget::setPalette() またはQWidget::setFont() の呼び出しによる変更は継承されます。それらは、それぞれのブラシやフォントが明示的に設定されていない、既存および将来のすべての子ウィジェットに継承されます。

C++ 名前空間内のウィジェット

タイプ・セレクタは、特定のタイプのウィジェットのスタイル設定に使用できます。例えば

class MyPushButton : public QPushButton {
    // ...
}

// ...
qApp->setStyleSheet("MyPushButton { background: yellow; }");

Qt Style Sheet は、ウィジェットの QObject::className() を使用して、タイプ・セレクタを適用するタイミングを決定します。カスタムウィジェットが名前空間内にある場合、QObject::className() は <namespace>::<classname> を返します。これは、サブコントロールの構文と衝突します。この問題を解決するために、名前空間内のウィジェットにタイプセレクタを使用する場合、::-- に置き換える必要があります。例えば

namespace ns {
    class MyPushButton : public QPushButton {
        // ...
    }
}

// ...
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");

QObject プロパティの設定

4.3以降では、qproperty-<プロパティ名>構文を使用して、設計可能なQ_PROPERTY

例えば

MyLabel { qproperty-pixmap: url(pixmap.png); }
MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }
QPushButton { qproperty-iconSize: 20px 20px; }

プロパティがQ_ENUM で宣言された列挙型を参照する場合、その定数を数値ではなく名前で参照する必要があります。

注意: qproperty構文は、描画されるウィジェットを変更するので、注意して使用してください。また、qproperty構文が評価されるのは、スタイルによってウィジェットが研磨されるときの1回だけです。つまり、QPushButton:hover のような擬似状態で使用しようとしても機能しません。

©2024 The Qt Company Ltd. ここに含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。