樣式表語法
????????Qt 樣式表術語和語法規則幾乎與 HTML CSS 的相同。如果您已經了解 CSS,您可能可以快速瀏覽此部分。
樣式規則
????????樣式表由一系列樣式規則組成。樣式規則由選擇器和聲明組成。選擇器指定哪些小部件受該規則影響;聲明指定應在小部件上設置哪些屬性。例如:
QPushButton { color: red }
????????在上述樣式規則中,QPushButton
?是選擇器,{ color: red }
?是聲明。該規則指定?QPushButton?及其子類(例如,MyPushButton
)應使用紅色作為其前景色。
????????Qt 樣式表通常不區分大小寫(即?color
、Color
、COLOR
?和?cOloR
?指的是相同的屬性)。唯一的例外是類名、對象名?和 Qt 屬性名,它們區分大小寫。
????????多個選擇器可以為同一個聲明指定,使用逗號(,
)來分隔選擇器。例如,規則
QPushButton, QLineEdit, QComboBox { color: red }
????????相當于以下這三條規則的序列:
QPushButton { color: red }
QLineEdit { color: red }
QComboBox { color: red }
????????樣式規則的聲明部分是一系列property: value
對,括在花括號({}
)中,并以分號分隔。例如:
QPushButton { color: red; background-color: white }
????????請查看下面的屬性列表部分,以獲取 Qt 控件提供的屬性列表。
選擇器類型
選擇器 | 示例 | 解釋 | 實例代碼 |
---|---|---|---|
通用選擇器 | * | 匹配所有小部件。 | |
類型選擇器 | QPushButton | 匹配?QPushButton?及其子類的實例。 | |
屬性選擇器 | QPushButton[flat="false"] | 匹配不是扁平的QPushButton實例。您可以使用此選擇器來測試支持QVariant::toString()的任何 Qt屬性(有關詳細信息,請參閱toString()函數文檔)。此外,還支持特殊的 此選擇器還可用于測試動態屬性。有關使用動態屬性進行自定義的更多信息,請參閱使用動態屬性進行自定義。 與其使用 警告:如果在設置樣式表后 Qt 屬性的值發生更改,可能需要強制重新計算樣式表。實現此目的的一種方法是取消設置樣式表然后再次設置。 | |
類選擇器 | .QPushButton | 匹配?QPushButton?的實例,但不包括其子類。 這等同于? | |
id選擇器 | QPushButton#okButton | 匹配所有QPushButton實例,其對象名稱為okButton 。 | |
派生類選擇器 | QDialog QPushButton | 匹配所有作為QDialog的后代(子節點、孫節點等)的QPushButton實例。 | |
子選擇器 | QDialog > QPushButton | 匹配所有作為?QDialog?的直接子元素的?QPushButton?實例。 |
?子控件
????????對于復雜小部件的樣式設置,有必要訪問小部件的子控件,例如QComboBox的下拉按鈕或QSpinBox的上下箭頭。選擇器可能包含子控件,這使得能夠將規則的應用限制在特定的小部件子控件上。例如:
QComboBox::drop-down { image: url(dropdown.png) }
????????上述規則為所有QComboBox的下拉按鈕設置樣式。盡管雙冒號(::
)語法讓人想起 CSS3 偽元素,但 Qt 子控件在概念上與這些不同,并且具有不同的級聯語義。
?????????子控件始終相對于另一個元素(即參考元素)進行定位。此參考元素可以是小部件或另一個子控件。例如,默認情況下,“下拉列表”在“QComboBox”的填充矩形的右上角。默認情況下,“下拉列表”位于“下拉列表”子控件的內容矩形的中心。有關用于設置小部件樣式的子控件及其默認位置,請參閱下面的“可設置樣式的小部件列表”。
????????可使用子控件原點屬性更改要使用的原始矩形。例如,如果我們希望將下拉列表放置在QComboBox的邊距矩形中,而不是默認的填充矩形中,我們可以指定:
QComboBox {margin-right: 20px;
}
QComboBox::drop-down {subcontrol-origin: margin;
}
????????在 Margin 矩形內下拉列表的對齊方式使用子控件位置屬性進行更改。
????????寬度和高度屬性可用于控制子控件的大小。請注意,設置圖像會隱式設置子控件的大小。
?????????相對定位方案(位置:相對),允許子控件的位置偏離其初始位置。例如,當按下QComboBox的下拉按鈕時,我們可能希望內部的箭頭偏移以產生“按下”效果。要實現此目的,我們可以指定:
QComboBox::down-arrow {image: url(down_arrow.png);
}
QComboBox::down-arrow:pressed {position: relative;top: 1px; left: 1px;
}
????????絕對定位方案(位置:絕對)允許子控件的位置和大小相對于參考元素進行更改。
????????一旦定位,它們就與小部件一樣被對待,并且可以使用盒模型進行樣式設置。
????????請查看下面的子控件列表以獲取受支持的子控件列表,以及自定義 QPushButton 的菜單指示器子控件以獲取實際示例。
????????注意:對于復雜的小部件,如QComboBox和QScrollBar,如果自定義了一個屬性或子控件,那么所有其他屬性或子控件也必須進行自定義。
偽狀態
????????選擇器可能包含偽狀態,這些偽狀態表示根據小部件的狀態限制規則的應用。偽狀態出現在選擇器的末尾,中間有一個冒號(:
)。例如,當鼠標懸停在QPushButton?上時,以下規則適用:
QPushButton:hover { color: white }
????????偽狀態可以使用感嘆號運算符進行取反。例如,當鼠標未懸停在QRadioButton?上時,以下規則適用:
QRadioButton:!hover { color: red }
????????偽狀態可以鏈接,在這種情況下意味著邏輯“與”。例如,以下規則適用于鼠標懸停在已選中的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 }
????????這兩條規則都匹配名為?QPushButton?的實例,稱為?okButton
,并且對于?color
?屬性存在沖突。為了解決此沖突,我們必須考慮選擇器的特異性。在上述示例中,QPushButton#okButton
?被認為比?QPushButton
?更具特異性,因為它(通常)指的是單個對象,而不是類的所有實例。
????????同樣,具有偽狀態的選擇器比未指定偽狀態的選擇器更具特異性。因此,以下樣式表指定當鼠標懸停在QPushButton?上時,它應該具有白色文本,否則為紅色文本:
QPushButton:hover { color: white }
QPushButton { color: red }
????????這是個棘手的問題:
QPushButton:hover { color: white }
QPushButton:enabled { color: red }
????????在這里,兩個選擇器具有相同的特異性,因此,如果鼠標在啟用按鈕時懸停在其上,則第二條規則優先。如果在這種情況下我們希望文本為白色,我們可以像這樣重新排列規則:
QPushButton:enabled { color: red }
QPushButton:hover { color: white }
????????或者,我們可以使第一條規則更具體:
QPushButton:hover:enabled { color: white }
QPushButton:enabled { color: red }
????????在與類型選擇器結合時會出現類似的問題。考慮以下示例:
QPushButton { color: red }
QAbstractButton { color: gray }
????????這兩條規則適用于QPushButton實例(因為QPushButton繼承QAbstractButton),并且對于顏色屬性存在沖突。由于QPushButton繼承QAbstractButton,可能會讓人誤以為QPushButton
比QAbstractButton
更具體。然而,對于樣式表計算,所有類型選擇器具有相同的特異性,最后出現的規則優先。換句話說,顏色被設置為gray
對于所有QAbstractButton,包括QPushButton。如果我們確實希望QPushButton具有紅色文本,我們總是可以重新排列規則。
一個選擇器的特異性計算如下:
- 計算選擇器(= a)中 ID 屬性的數量
- 計算選擇器(= b)中其他屬性和偽類的數量
- 計算選擇器(= c)中元素名稱的數量
- 忽略偽元素(例如,子控件)。
將三個數字 a - b - c(在一個具有大基數的數字系統中)連接起來會產生特殊性。
示例:
* {} /* 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對象上設置一個樣式表:
????????QPushButton?上的樣式表強制?QPushButton(以及任何子部件)具有藍色文本,盡管應用程序范圍內的樣式表提供了更具體的規則集。
????????如果我們已經寫了,結果會是一樣的
myPushButton->setStyleSheet("color: blue");
????????只是如果QPushButton有子元素(這不太可能),樣式表對它們將沒有影響。
????????樣式表級聯是一個復雜的主題。請參考CSS2 規范以獲取詳細信息。請注意,Qt 目前尚未實現!important
。
繼承
????????在經典的 CSS 中,當一個項目的字體和顏色未明確設置時,它會自動從父項繼承。在使用 Qt 樣式表時,一個小部件不會自動從其父部件繼承其字體和顏色設置。
????????例如,考慮在QGroupBox?內的QPushButton?:
qApp->setStyleSheet("QGroupBox { color: red; } ");
????????QPushButton?未設置明確的顏色。因此,它沒有繼承其父QGroupBox的顏色,而是采用了系統顏色。如果我們要為QGroupBox及其子元素設置顏色,可以這樣寫:
qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");
????????相比之下,設置字體并使用QWidget::setFont() 和?QWidget::setPalette() 進行傳播會傳播到子部件。
命名空間中的小部件
????????類型選擇器可用于為特定類型的小部件設置樣式。例如:
class MyPushButton : public QPushButton {// ...
}// ...
qApp->setStyleSheet("MyPushButton { background: yellow; }");
????????Qt 樣式表使用小部件的 QObject::className() 來確定何時應用類型選擇器。當自定義小部件在命名空間內時,QObject::className() 返回?::。這與?子控件?的語法沖突。為了克服這個問題,當對命名空間內的小部件使用類型選擇器時,我們必須將“::”替換為“--”。例如,
namespace ns {class MyPushButton : public QPushButton {// ...}
}// ...
qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");
設置 QObject 屬性
????????從 4.3 及以上版本開始,任何可設計的Q_PROPERTY都可以使用 qproperty-<屬性名稱>語法進行設置。
????????例如:
MyLabel { qproperty-pixmap: url(pixmap.png); }
MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }
QPushButton { qproperty-iconSize: 20px 20px; }
????????如果屬性引用使用 Q_ENUMS 聲明的枚舉,您應該通過名稱引用其常量,即,不是它們的數值。