Qt 樣式錶術語和語法規則,幾乎等同 HTML CSS。若已經瞭解 CSS,就可以快速略讀本章節。
樣式錶由一係列樣式規則組成。 樣式規則 由選擇器和聲明組成。 選擇器 指定受規則影響的 Widget; 聲明 指定應該為 Widget 設置哪些特性。例如:
QPushButton { color: red }
在上文樣式規則中,
QPushButton
是選擇器和
{ color: red }
是聲明。規則指定
QPushButton
及其子類 (如
MyPushButton
) 應該使用紅色作為它們的前景顔色。
Qt 樣式錶一般不區分大小寫 (即
color
,
Color
,
COLOR
,和
cOloR
引用相同特性)。唯一例外是類、
對象名稱
、及 Qt 特性名稱,它們要區分大小寫。
可以為同一聲明指定幾個選擇器,使用逗號 (
,
) 分隔選擇器。例如,規則
QPushButton, QLineEdit, QComboBox { color: red }
相當於這 3 條規則序列:
QPushButton { color: red } QLineEdit { color: red } QComboBox { color: red }
樣式規則的聲明部分是列錶化的
property: value
對,封閉於花括號 (
{}
) 並采用 ; 分號分隔。例如:
QPushButton { color: red; background-color: white }
見 特性列錶 下文章節,瞭解由 Qt Widgets 提供的特性列錶。
到目前為止,所有範例均使用最簡單選擇器類型 (類型選擇器)。Qt 樣式錶支持所有 由 CSS2 定義的選擇器 。下錶匯總瞭最有用的選擇器類型。
| 選擇器 | 範例 | 解釋 |
|---|---|---|
| 通用選擇器 |
*
|
匹配所有 Widget。 |
| 類型選擇器 |
QPushButton
|
匹配實例化的 QPushButton 及其子類。 |
| 特性選擇器 |
QPushButton[flat="false"]
|
匹配實例化的
QPushButton
that are not
flat
. You may use this selector to test for any Qt
property
支持
QVariant::toString
() (見
toString()
function documentation for details). In addition, the special
class
property is supported, for the name of the class.
This selector may also be used to test dynamic properties. For more information on customization using dynamic properties, refer to 定製使用動態特性 .
Instead of
警告: If the value of the Qt property changes after the style sheet has been set, it might be necessary to force a style sheet recomputation. One way to achieve this is to unset the style sheet and set it again. |
| 類選擇器 |
.QPushButton
|
匹配實例化的
QPushButton
,而不是其子類。
這相當於
|
| ID 選擇器 |
QPushButton#okButton
|
匹配所有
QPushButton
instances whose
對象名稱
is
okButton
.
|
| 後代選擇器 |
QDialog QPushButton
|
匹配所有實例化的 QPushButton that are descendants (children, grandchildren, etc.) of a QDialog . |
| 子級選擇器 |
QDialog > QPushButton
|
匹配所有實例化的 QPushButton that are direct children of a QDialog . |
For styling complex widgets, it is necessary to access subcontrols of the widget, such as the drop-down button of a QComboBox or the up and down arrows of a QSpinBox 。選擇器可能包含 subcontrols that make it possible to restrict the application of a rule to specific widget subcontrols. For example:
QComboBox::drop-down { image: url(dropdown.png) }
The above rule styles the drop-down button of all
QComboBox
es. Although the double-colon (
::
) syntax is reminiscent of CSS3 Pseudo-Elements, Qt Sub-Controls differ conceptually from these and have different cascading semantics.
Sub-controls are always positioned with respect to another element - a reference element. This reference element could be the widget or another Sub-control. For example, the ::drop-down 的 QComboBox is placed, by default, in the top right corner of the Padding rectangle of the QComboBox 。 ::drop-down is placed, by default, in the Center of the Contents rectangle of the ::drop-down 子控件。見 可樣式化 Widget 列錶 below for the Sub-controls to use to style a widget and their default positions.
The origin rectangle to be used can be changed using the subcontrol-origin property. For example, if we want to place the drop-down in the margin rectangle of the QComboBox instead of the default Padding rectangle, we can specify:
QComboBox { margin-right: 20px; } QComboBox::drop-down { subcontrol-origin: margin; }
The alignment of the drop-down within the Margin rectangle is changed using subcontrol-position 特性。
The width and height properties can be used to control the size of the Sub-control. Note that setting a image implicitly sets the size of a Sub-control.
The relative positioning scheme ( position : relative), allows the position of the Sub-Control to be offset from its initial position. For example, when the QComboBox 's drop-down button is pressed, we might like the arrow inside to be offset to give a "pressed" effect. To achieve this, we can specify:
QComboBox::down-arrow { image: url(down_arrow.png); } QComboBox::down-arrow:pressed { position: relative; top: 1px; left: 1px; }
絕對位置方案 ( position : absolute), allows the position and size of the Sub-control to be changed with respect to the reference element.
Once positioned, they are treated the same as widgets and can be styled using the Box 模型 .
見 子控件列錶 下文瞭解支持的子控件列錶,和 定製 QPushButton 的菜單指示器子控件 瞭解現實範例。
注意: 采用復雜 Widget,譬如 QComboBox and QScrollBar , if one property or sub-control is customized, all the other properties or sub-controls must be customized as well.
選擇器可以包含
僞狀態
that denote that restrict the application of the rule based on the widget's state. Pseudo-states appear at the end of the selector, with a colon (
:
) in between. For example, the following rule applies when the mouse hovers over a
QPushButton
:
QPushButton:hover { color: white }
Pseudo-states can be negated using the exclamation operator. For example, the following rule applies when the mouse does not hover over a QRadioButton :
QRadioButton:!hover { color: red }
Pseudo-states can be chained, in which case a logical AND is implied. For example, the following rule applies to when the mouse hovers over a checked QCheckBox :
QCheckBox:hover:checked { color: white }
Negated Pseudo-states may appear in Pseudo-state chains. For example, the following rule applies when the mouse hovers over a QPushButton that is not pressed:
QPushButton:hover:!pressed { color: blue; }
If needed, logical OR can be expressed using the comma operator:
QCheckBox:hover, QCheckBox:checked { color: white }
Pseudo-states can appear in combination with subcontrols. For example:
QComboBox::drop-down:hover { image: url(dropdown_bright.png) }
見 僞狀態列錶 section below for the list of pseudo-states provided by Qt widgets.
Conflicts arise when several style rules specify the same properties with different values. Consider the following style sheet:
QPushButton#okButton { color: gray } QPushButton { color: red }
兩者規則匹配
QPushButton
實例稱為
okButton
and there is a conflict for the
color
property. To resolve this conflict, we must take into account the
specificity
of the selectors. In the above example,
QPushButton#okButton
is considered more specific than
QPushButton
, because it (usually) refers to a single object, not to all instances of a class.
Similarly, selectors with pseudo-states are more specific than ones that do not specify pseudo-states. Thus, the following style sheet specifies that a QPushButton should have white text when the mouse is hovering over it, otherwise red text:
QPushButton:hover { color: white } QPushButton { color: red }
Here's a tricky one:
QPushButton:hover { color: white } QPushButton:enabled { color: red }
Here, both selectors have the same specificity, so if the mouse hovers over the button while it is enabled, the second rule takes precedence. If we want the text to be white in that case, we can reorder the rules like this:
QPushButton:enabled { color: red } QPushButton:hover { color: white }
Alternatively, we can make the first rule more specific:
QPushButton:hover:enabled { color: white } QPushButton:enabled { color: red }
A similar issue arises in conjunction with Type Selectors. Consider the following example:
QPushButton { color: red } QAbstractButton { color: gray }
Both rules apply to
QPushButton
實例 (由於
QPushButton
繼承
QAbstractButton
) and there is a conflict for the
color
特性。因為
QPushButton
繼承
QAbstractButton
, it might be tempting to assume that
QPushButton
is more specific than
QAbstractButton
. However, for style sheet computations, all Type Selectors have the same specificity, and the rule that appears last takes precedence. In other words,
color
被設為
gray
for all
QAbstractButton
s, including
QPushButton
s. If we really want
QPushButton
s to have red text, we can always reorder the rules.
為確定規則的特異性,Qt 樣式錶遵循 CSS2 規範 :
A selector's specificity is calculated as follows:
Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity.
一些範例:
* {} /* 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 , on parent widgets, and on child widgets. An arbitrary widget's effective style sheet is obtained by merging the style sheets set on the widget's ancestors (parent, grandparent, etc.), as well as any style sheet set on the QApplication .
When conflicts arise, the widget's own style sheet is always preferred to any inherited style sheet, irrespective of the specificity of the conflicting rules. Likewise, the parent widget's style sheet is preferred to the grandparent's, etc.
One consequence of this is that setting a style rule on a widget automatically gives it precedence over other rules specified in the ancestor widgets' style sheets or the QApplication style sheet. Consider the following example. First, we set a style sheet on the QApplication :
qApp->setStyleSheet("QPushButton { color: white }");
Then we set a style sheet on a QPushButton 對象:
myPushButton->setStyleSheet("* { color: blue }");
樣式錶在 QPushButton 強製 QPushButton (and any child widget) to have blue text, in spite of the more specific rule set provided by the application-wide style sheet.
The result would have been the same if we had written
myPushButton->setStyleSheet("color: blue");
except that if the QPushButton had children (which is unlikely), the style sheet would have no impact on them.
Style sheet cascading is a complex topic. Refer to the
CSS2 規範
for the gory details. Be aware that Qt currently doesn't implement
!important
.
In classic CSS, when font and color of an item is not explicitly set, it gets automatically inherited from the parent. By default, when using Qt Style Sheets, a widget does not automatically inherit its font and color setting from its parent widget.
例如,認為 QPushButton 在 QGroupBox :
qApp->setStyleSheet("QGroupBox { color: red; } ");
The QPushButton does not have an explicit color set. Hence, instead of inheriting color of its parent QGroupBox , it has the system color. If we want to set the color on a QGroupBox and its children, we can write:
qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");
In contrast, setting a font and palette using QWidget::setFont () 和 QWidget::setPalette () propagates to child widgets.
If you would prefer that the font and palette propagate to child widgets, you can set the Qt::AA_UseStyleSheetPropagationInWidgetStyles 標誌,像這樣:
用法:
QCoreApplication::setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles, true);
When the widget-style font and palette propagation is enabled, font and palette changes made through Qt Style Sheets will behave as though the user had manually called the corresponding QWidget::setPalette () 和 QWidget::setFont () methods on all of the QWidgets targeted by the style sheet. If this would have caused propagation in C++, it will cause propagation in style sheets and visa versa.
The Type Selector can be used to style widgets of a particular type. For example,
class MyPushButton : public QPushButton { // ... } // ... qApp->setStyleSheet("MyPushButton { background: yellow; }");
Qt Style Sheet uses QObject::className() of the widget to determine when to apply the Type Selector. When custom widgets are inside namespaces, the QObject::className() returns <namespace>::<classname>. This conflicts with the syntax for 子控件 . To overcome this problem, when using the Type Selector for widgets inside namespaces, we must replace the "::" with "--". For example,
namespace ns { class MyPushButton : public QPushButton { // ... } } // ... qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");
從 4.3 及以上,任何可設計 Q_PROPERTY can be set using the qproperty-<property name> syntax.
例如,
MyLabel { qproperty-pixmap: url(pixmap.png); }
MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }
QPushButton { qproperty-iconSize: 20px 20px; }
If the property references an enum declared with Q_ENUMS, you should reference its constants by name, i.e., not their numeric value.