這幾天學習了下QSS空間的美化,以下是一些基礎知識的總結!
建議QSS的使用步驟:先在Designer裏面寫QSS,能實時的看到效果,滿意後寫到qss文件中
從文件中讀取QSS複製給QString然後應用程序設置樣式表,例如:
QFile file(":/sourceFile/styleSheet.qss");
file.open(QEODevice::ReadOnly | QIODevice::Text);
QString strStyleSheet(file.readAll());
app.setStyleSheet(strStyleSheet);
常用的設置:
QLabel {
/* 相當於 font: bold 50px "Snell Roundhand"; */
font-size: 50px;
font-weight: bold;
font-family: "Snell Roundhand";
color: white;
/* 相當於 background: lightgray url(:/resources/horizontal-add-line.png); */
background-color: lightgray;
background-image: url(:/resources/horizontal-add-line.png);
/* 相當於 border: 5px solid gray; */
border-width: 5px;
border-color: gray;
border-style: solid;
border-radius: 10px;
}
<pre name="code" class="cpp">設置字體常用:
font-style <italic 斜體 oblique 傾斜 normal 正常>
font-size <設置字體的大小>
font-weight <設置字體的粗細 bold 相當於700左右>
font-family <設置字體的系列 如arial courier等>
color <字體顏色>
設置背景圖片有以下設置:
background-color <背景顏色>
background-position <位置>
background-repeat <重複>
background-attachment <拉伸、滾動>
background-image <資源圖片>
background-position可選值:
top left、top center、top right、
Center left、Center center、Center right、
bottom left、bottom center、bottom right
repeat可選值:
repeat-x <水平重複> repeat-y<垂直重複> no-repeat<不重複>
attachment可選值:
scroll <背景隨着滾動條滾動> 、fixed <不滾動>
background-image中url 中的路徑可以是:
資源文件的路徑(:/ 開頭)
絕對路徑
相對於可執行文件的相對路徑
設置邊框常用:
border-width <邊框寬>
border-style <邊框樣式 如 solid 實線等>
border-color <顏色>
border-radius <圓角>
border-image <圖片 如:url(":/image.png") 10 10 10 10 repeat stretch>
border-image參數說
url:資源文件路徑
四個數字分別是:<注意這些數字並沒有單位>
背景圖片中 最上面 的10px高的圖像填充到widget的border-top
背景圖片中 最右邊 的10px高的圖像填充到widget的border-right
背景圖片中 最下面 的10px高的圖像填充到widget的border-bottom
背景圖片中 最左邊 的10px高的圖像填充到widget的border-left
數字後的第一個參數 repeat|round|stretch 指定水平方向的縮放或平鋪
數字後的第二個參數 repeat|round|stretch 指定垂直方向的縮放或平鋪
盒子模型:
每個 Widget 所在的範圍都是一個矩形區域(無規則窗口也是一個矩形,只是有的地方是透明的,看上去不是一個矩形而已),像是一個盒子一樣。QSS 支持盒子模型(Box Model),和 CSS 的盒子模型是一樣的,由 4 個部分組成:content, padding, border, margin,也就是說,Widget 的矩形區域,用這 4 個矩形表示
content
: 繪製內容的矩形區域(如繪製文本、圖片),Qt 自帶的 widget 都是在 content 區裏繪製內容,這只是一個約定,只要你願意,也可以在繪製到 padding, border, margin 區padding
: 內容區和邊框之間的間隔border
: 邊框,可視化的顯示一個 widget 的邏輯範圍,而不一定是 widget 所佔矩形區域的實際大小margin
: 想像 widget 的矩形區域有一個隱形的邊框,margin 就是 border 和這個隱形邊框之間的間
QSS選擇器:
以下內容轉載自:http://qtdebug.com/QSS-Selector.html選擇器決定了 style sheet 作用於哪些 Widget,QSS 支持 CSS2 定義的所有選擇器。
QSS 的選擇器有:
- 通用選擇器 *
- 類型選擇器
- 類選擇器
- ID 選擇器
- 屬性選擇器
- 包含選擇器
- 子元素選擇器
- 僞類選擇器
- Subcontrol 選擇器
很多時候,可以使用不同的選擇器實現相同效果的樣式,使用非常靈活。
通用選擇器 *
*
作爲選擇器,作用於所有的 Widget。
類型選擇器
類名
作爲選擇器,作用於它自己和它的所有子類。
QFrame {
background: gray;
}
使用了類型選擇器 QFrame
,所以 QFrame 和它的子類 QLable,QLCDNumber,QTableWidget 等的背景會是灰色的,QPushButton 不是 QFrame 的子類,所以不受影響:
類選擇器
. + 類名
或者 . + class 的屬性值
作爲選擇器,只會作用於它自己,它的子類不受影響。
#include <QApplication>
#include <QPushButton>
#include <QHBoxLayout>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
app.setStyleSheet("QWidget { background: gray; }");
QWidget *window = new QWidget();
QPushButton *openButton = new QPushButton("打開", window);
QPushButton *closeButton = new QPushButton("關閉", window);
QPushButton *saveButton = new QPushButton("保存", window);
QHBoxLayout *layout = new QHBoxLayout(window);
layout->addWidget(openButton);
layout->addWidget(closeButton);
layout->addWidget(saveButton);
window->setLayout(layout);
window->show();
return app.exec();
}
window, openButton, closeButton 和 saveButton 的背景都變成灰色的了,如果只想要 window 的背景是灰色的,按鈕的背景不變,可以這麼設置
/* 把 QWidget 改成 .QWidget */
app.setStyleSheet(".QWidget {background: gray;}")
如果 openButton 和 closeButton 的背景是洋紅色的,但是 saveButton 不受影響,則可以使用 . + class 的屬性值
作爲類選擇器來設置
app.setStyleSheet(".QWidget { background: gray; }"
".QPushButton[level='dangerous'] { background: magenta; }");
// .RedButton 將作爲類選擇器
openButton->setProperty("class", "RedButton");
closeButton->setProperty("class", "RedButton");
屬性的值可以用單引號,雙引號括起來,如果值沒有空格,甚至可以不用引號,但不推薦這麼做:
.QPushButton[level="dangerous"]
.QPushButton[level='dangerous']
.QPushButton[level=dangerous]
ID 選擇器
# + objectName
作爲選擇器,只作用於用此 objectName 的對象(多個對象可以使用同一個 objectName,但是不推薦這麼做)。如上面的程序, openButton 和 closeButton 的背景是洋紅色的,但是 saveButton 不受影響,也可以使用 ID 選擇器
來實現:
app.setStyleSheet(".QWidget { background: gray; }"
"#openButton, #closeButton { background: magenta; }");
// #openButton 和 #closeButton 作爲 ID 選擇器
openButton->setObjectName("openButton");
closeButton->setObjectName("closeButton");
屬性選擇器
選擇器[屬性="值"]
作爲選擇器,這個屬性可用通過 object->property(propertyName) 訪問的,Qt 裏稱爲 Dynamic Properties
。
如上面的程序, openButton 和 closeButton 的背景是洋紅色的,但是 saveButton 不受影響,也可以使用屬性選擇器 來實現:
app.setStyleSheet(".QWidget { background: gray; }"
"QPushButton[level=\"dangerous\"] { background: magenta; }");
openButton->setProperty("level", "dangerous");
closeButton->setProperty("level", "dangerous");
QSS 會把所有 QPushButton 中 level 屬性值爲 dangerous 按鈕的背景繪製爲洋紅色,其他按鈕的背景色不受這個 QSS 影響。
包含選擇器
英語叫做 Descendant Selector
,descendant 的表達比較到位。
選擇器之間用空格隔開
,作用於 Widget 的 子Widget
,子Widget 的 子Widget
,……,子子孫孫,無窮盡也。
QFrame {
background: gray;
}
QFrame QPushButton {
border: 2px solid magenta;
border-radius: 10px;
background: white;
padding: 2px 15px;
}
頂部的 QPushButton 是 QFrame 的 descendant,所以 QSS 生效了,左下角的 QPushButton 的 parent 是 QWidget,所以 QSS 不起作用:
子元素選擇器
選擇器之間用 > 隔開
,作用於 Widget 的直接 子Widget
。
QFrame {
background: gray;
}
QFrame > QPushButton {
border: 2px solid magenta;
border-radius: 10px;
background: white;
padding: 2px 15px;
}
按鈕 Child of QGroupBox
的 parent 是 QGroupBox,QGroupBox 的 parent 是 QFrame,所以 Child of QGroupBox
雖然是 QFrame 的 子Widget
的 子Widget
,但不是 QFrame 的直接 子Widget
,故
QSS 不起作用,而 按鈕 Child of QFrame
的 parent 是 QFrame,所以它的樣式改變了:
僞類選擇器
選擇器:狀態
作爲選擇器,支持 !
操作符,表示 非
。
QPushButton:hover { color: white }
QCheckBox:checked { color: white }
QCheckBox:!checked { color: red }
鼠標放到 QPushButton 上時,它的文字爲白色,QCheckBox 選中時文字爲白色,未選中時爲紅色。
僞類選擇器還支持鏈式規則:選擇器:狀態1:狀態2:狀態3
,狀態之間使用邏輯與,同時滿足條件樣式才生效
QCheckBox:hover:checked { color: white }
鼠標 放到
選中的
QCheckBox 上時,它的字體爲白色。
常用僞類選擇器有:
僞類 | 說明 |
---|---|
:disabled | Widget 被禁用時 |
:enabled | Widget 可使用時 |
:focus | Widget 得到輸入焦點 |
:hover | 鼠標放到 Widget 上 |
:pressed | 鼠標按下時 |
:checked | 被選中時 |
:unchecked | 未選中時 |
:has-children | Item 有子 item,例如 QTreeView 的 item 有子 item 時 |
:has-siblings | Item 有 兄弟,例如 QTreeView 的 item 有兄弟 item 時 |
:open | 打開或展開狀態,例如 QTreeView 的 item 展開,QPushButton 的菜單彈出時 |
:closed | 關閉或者非展開狀態 |
:on | Widget 狀態是可切換的(toggle), 在 on 狀態 |
:off | Widget 狀態是可切換的(toggle), 在 off 狀態 |
僞類的說明寫成中文怎麼感覺都很彆扭,慚愧,表達能力欠佳,在此僅作爲拋磚引玉吧,更多更詳細的內容請參考 Qt 的幫助文檔,搜索 Qt Style Sheets Reference
,查看最下面的 List of Pseudo-States
。
當然,這些僞類並不是對任何 Widget 都起作用,例如 QLabel 沒有 :checked 狀態,即使設置了樣式 QLabel:checked {color: red}
,對 QLabel 也是沒有效果的,只有 Widget 支持某個狀態,那麼對應的僞類的樣式纔有作用。
Subcontrol 選擇器
選擇器::subcontrol
作爲選擇 Subcontrol 的選擇器。
有些 Widget 是由多個部分組合成的,例如 QCheckBox 由 icon(indicator) 和 text 組成,可以使用 選擇器::subcontrol
來設置 subcontrol 的樣式:
QCheckBox::indicator {
width: 20px;
height: 20px;
}
QCheckBox {
spacing: 8px;
}
常用的 Subcontrol 有:
Subcontrol | 說明 |
---|---|
::indicator | A QCheckBox, QRadioButton, checkable QMenu item, or a checkable QGroupBox's indicator |
::menu-indicator | A QPushButton's menu indicator |
::item | A QMenu, QMenuBar, or QStatusBar's item |
::up-button | A QSpinBox or QScrollBar's up button |
::down-button | A QSpinBox or QScrollBar's down button |
::up-arrow | A QSpinBox, QScrollBar, or QHeaderView's up arrow |
::down-arrow | A QSpinBox, QScrollBar, or QHeaderView's down arrow |
::drop-down | A QComboBox's drop-down arrow |
::title | A QGroupBox or QDockWidget's title |
::groove | A QSlider's groove |
::chunk | A QProgressBar's progress chunk |
::branch | A QTreeView's branch indicator |
更多更詳細的內容請參考 Qt 的幫助文檔,搜索 Qt Style Sheets Reference
,查看最下面的 List of Sub-Controls
。