QSS基礎知識學習

這幾天學習了下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");

屬性的值可以用單引號,雙引號括起來,如果值沒有空格,甚至可以不用引號,但不推薦這麼做:
  1. .QPushButton[level="dangerous"]
  2. .QPushButton[level='dangerous']
  3. .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


發佈了36 篇原創文章 · 獲贊 158 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章