網(wǎng)站icp備案號怎么查詢/搜索引擎優(yōu)化實訓報告
什么是QSS
QSS稱為Qt Style Sheets也就是Qt樣式表,它是Qt提供的一種用來自定義控件外觀的機制。QSS大量參考了CSS的內容,只不過QSS的功能比CSS要弱很多,體現(xiàn)在選擇器要少,可以使用的QSS屬性也要少很多,并且并不是所有的屬性都可以用在Qt的所有控件上。
QSS在Qt程序中的使用辦法
首先將QSS寫在文件中,然后利用如下的代碼設置QSS:
MainWidget::MainWidget(QWidget *parent) :QWidget(parent),ui(new Ui::MainWidget)
{//應用樣式 apply the qss styleQFile file(":/qss/main.qss");file.open(QFile::ReadOnly);QTextStream filetext(&file);QString stylesheet = filetext.readAll();this->setStyleSheet(stylesheet);file.close();
}
該段代碼寫在ui界面的后臺cpp文件的構造函數(shù)中,主要是this->setStyleSheet()函數(shù)的設置功能,要說明的是該函數(shù)除了可以對整個當前構造數(shù)所在的那個類所表示的ui進行整體應用樣式以外,setStyleSheet()函數(shù)本身是QWidget的成員函數(shù),幾乎Qt中的大多數(shù)控件都可以直接使用該函數(shù)分別設置自己的樣式。
QSS的語法規(guī)則
QSS的語法規(guī)則幾乎與CSS相同。一條QSS的樣式是由兩部分組成的,一部分是選擇器指定了哪些控件會受到影響,另一部分是指定了屬性的值,表示這些控件的哪些屬性會受到影響。例如:
QPushButton { color: red }
QPushButton表示選擇器,指定了所有的QPushButton或者是QPushButton的子類會受到影響,注意凡是繼承自QPushButton的子類也會受到影響,這是與CSS中不同的地方,因為CSS應用的都是一些標簽,沒有類的層次結構,更加沒有子類的概念。而后面的{color:red}則是規(guī)則的定義,表明指定前景顏色是紅色。整個意思就是設置QPushButton類以及其子類的所有實例的前景色是紅色。
如果MyButton繼承自QPushButton,那么上面的規(guī)則也會應用到所有MyButton控件上,但是如果規(guī)則是如下的:
MyButton{color:red}
則只會對MyButton的實例應用紅色的前景顏色,而對QPushButton的實例沒有應用。
QSS的選擇器類型
1.通配選擇器:* ; 匹配所有的控件
2.類型選擇器:QPushButton ; 匹配所有QPushButton和其子類的實例
3.屬性選擇器:QPushButton[flat=“false”]; 匹配所有flat屬性是false的QPushButton實例,注意該屬性可以是自定義的屬性,不一定非要是類本身具有的屬性
4.類選擇器: .QPushButton ; 匹配所有QPushButton的實例,但是并不匹配其子類。這是與CSS中的類選擇器不一樣的地方,注意前面有一個點號
5.ID選擇器: #myButton; 匹配所有id為myButton的控件實例,這里的id實際上就是objectName指定的值
6.后代選擇器: QDialog QPushButton ; 所有QDialog容器中包含的QPushButton,不管是直接的還是間接的
7.子選擇器: QDialog > QPushButton; 所有QDialog容器下面的QPushButton,其中要求QPushButton的直接父容器是QDialog
另外上面所有的這些選擇器可以聯(lián)合使用,并且支持一次設置多個選擇器類型,用逗號隔開,這點與CSS一樣,例如#frameCut,#frameInterrupt,#frameJoin 表示所有這些id使用一個規(guī)則。#mytable QPushButton 表示選擇所有id為mytable的容器下面的QPushButton實例
QSS子控件
QSS的子控件實際上也是選擇器的一種,因為這種選擇器與CSS有一些不同,所以單獨拿出來說,QSS的子控件選擇器是應用在一些復合控件上的,典型的例如QComboBox,該控件的外觀包含幾個部分,一般情況下有一個矩形的外邊框,右邊有一個向下的箭頭用于提示點擊之后會有彈出下拉列表。例如:
QComboBox::drop-down { image: url(dropdown.png) }
上面的樣式指定所有QComboBox的下拉箭頭的圖片為自定義的圖片dropdown.png
::dropdown子控件選擇器也可以與上面提到的選擇器一起聯(lián)合使用:
QComboBox#myQComboBox::drop-down { image: url(dropdown.png) }
指定id名為myQComboBox的QComboBox控件的下拉箭頭的自定義圖片,要注意的是子控件選擇器實際上是選擇復合控件中的一部分,也就是說對復合控件中的一部分應用樣式,例如為QComboBox的下拉箭頭指定圖片,而不是為QComboBox本身指定圖片。
QSS為很多復雜的復合控件提供了子控件的定義,以方便對這些復合控件的各個部分進行樣式設置。限于篇幅,本文也不能將這些可用的子控件都列出來,在安裝QtCreator之后自帶的幫助中就有很詳細的描述。
QSS偽狀態(tài)
QSS的偽狀態(tài)選擇器實際上與CSS中的類似,是以冒號開頭的一個選擇表達式,例如:hover表示當鼠標經過時候的狀態(tài)。他限制了當控件在某一種狀態(tài)下的時候才能應用QSS規(guī)則,偽狀態(tài)只能描述一個控件的狀態(tài),或者是一個復合控件中的子控件的狀態(tài),所以該偽狀態(tài)選擇器只能放在選擇器的最后面,例如:
QComboBox:hover{background-color:red;}
該規(guī)則表示當鼠標經過QComboBox上面的時候,其背景顏色指定為紅色,該偽狀態(tài) :hover描述的是QComboBox的狀態(tài)。
偽狀態(tài)除了描述選擇器選擇的控件以外,還可以描述子控件選擇器所選擇的復合控件中的子控件的狀態(tài),例如
QComboBox::drop-down:hover{background-color:red;}
表示當鼠標經過QComboBox的下拉箭頭的時候,該下拉箭頭的背景顏色變成紅色。
此外偽狀態(tài)可以用一個感嘆號表示否,例如:hover表示鼠標經過,而:!hover表示鼠標沒有經過的狀態(tài)。幾個偽狀態(tài)可以同時一起使用,例如:
QCheckBox:hover:checked { color: white }
指定一個當鼠標經過一個選中的QCheckBox的時候,設置其文字的前景顏色為白色。
QSS提供了很多的偽狀態(tài),一些偽狀態(tài)只能用在特定的控件上,具體有哪些偽狀態(tài),在Qt的幫助里面有詳細的列表,限于篇幅這里也不列出了。
QSS級聯(lián)與沖突
QSS中的級聯(lián)包含幾個方面的概念,一個是當在同一個控件上應用兩個不同的規(guī)則,那么應該應用哪一個規(guī)則的問題,也就是如何解決這種沖突。二個是在一個容器控件上設置的QSS規(guī)則會對容器里面的控件產生效果(這要取決于容器控件上設置的QSS規(guī)則是什么樣的規(guī)則,如果容器控件上設置的QSS規(guī)則僅僅針對容器控件本身則該規(guī)則對子控件沒有影響,如果該QSS規(guī)則里面有對子控件的設置,則自然會對子控件產生效果),級聯(lián)問題是解決當一個控件被層層父容器包裹,并且在每一層的父容器上都有對該控件的樣式設置的時候,該控件的最終效果是合并這些父容器上的QSS效果。
沖突問題:
QPushButton#okButton { color: gray }
QPushButton { color: red }
這兩條規(guī)則都會應用到名為okButton的按鈕上,但是他們?yōu)橥粋€屬性設置了不同的顏色,這會有沖突,那么要解決這樣的沖突就必須考慮到選擇器的特異性(這個詞怎么理解,我理解為這個特異性為更加特殊,實際上CSS上用權重表示這里的特異性),顯然QPushButton#okButton僅僅針對對象名為okButton的控件有效果,而QPushButton卻對所有的QPushButton的實例或者是其子類的實例有效果,顯然QPushButton#okButton選擇器更加特殊,也就是更具有特異性。所以最終okButton前景色被應用為灰色。如果兩條規(guī)則的特異性一樣,那么就選擇放在后面的那一條。
另外如果一個選擇器應用了偽狀態(tài),而另一個沒有,那么應用了偽狀態(tài)的選擇器要更加特殊,例如:
QPushButton:hover { color: white }
QPushButton { color: red }
顯然QPushButton:hover比單純的QPushButton更加具有特異性。這兩條規(guī)則表示當鼠標放在按鈕上的時候文字是白色,其他情況下都是紅色。
如下面兩個規(guī)則的特異性是一樣的,那么應該是如何應用呢:
QPushButton:hover { color: white } //如果鼠標經過則前景白色
QPushButton:enabled { color: red } //如果按鈕是enabled狀態(tài)則前景紅色
所以默認情況下前景文字是紅色的,當鼠標經過的時候并不會變成白色,因為他們的特異性是一樣的,所以選擇后面的,也就是紅色。
那么換一下順序會怎樣呢:
QPushButton:enabled { color: red } //如果按鈕是enabled狀態(tài)則前景紅色
QPushButton:hover { color: white } //如果鼠標經過則前景白色
當鼠標經過的時候,就變成白色的了,因為他們的特異性一樣,所以選擇后面的規(guī)則,也就是鼠標經過前景變成白色。
如果把其中的一條的特異性增加,例如:
QPushButton:hover:enabled { color: white }
QPushButton:enabled { color: red }
那么第一條的特異性比第二條大,所以應用第一條的規(guī)則。
另外一種特異性發(fā)生在類型選擇器上:
QPushButton { color: red } //應用在所有的QPushButton上
QAbstractButton { color: gray } //應用在所有的QAbstractButton上
而在類的繼承結構上,QAbstractButton是QPushButton的父類,顯然QPushButton更加具有特異性,所以QPushButton的前景顏色被應用為紅色,而不是灰色。有沒有一個辦法來確定兩條QSS規(guī)則的特異性大小呢,其實QSS使用的特異性的計算方法與CSS是一樣的,詳細可以參考CSS2的文檔規(guī)范,這里還是簡要的說明一下,特異性這個東西在CSS中一般被稱為權重,權重越大的越優(yōu)先使用,CSS的計算規(guī)則如下:
1.計算一條規(guī)則中id選擇器的個數(shù),假設存放在變量a中
2.計算一條規(guī)則中類選擇器和屬性選擇器的個數(shù),存放在變量b中
3.計算一條規(guī)則中的類型選擇器的個數(shù),存放在變量c中
4.忽略偽元素,對應QSS中的子控件
下面是具體的計算方法:
* {} /* 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 */
上面的計算規(guī)則是CSS的計算規(guī)則,同樣可以應用的QSS上。
關于級聯(lián):
QSS可以設置在QApplication上,也可以設置在一個部件的容器部件上,也可以設置在子孫部件上,一個部件最終使用的樣式效果是合并了他的所有父容器,祖父容器等上面設置的所有樣式的結果,這些設置會進行疊加。如果在級聯(lián)過程中發(fā)生了沖突,例如部件本身指定的前景顏色為綠色,而其父親容器為其指定的前景顏色為紅色,此時就選擇部件本身設置的樣式效果。例如:
qApplication->setStyleSheet("QPushButton { color: white }");
myPushButton->setStyleSheet("* { color: blue }");
第一條語句表示在QApplication上設置QPushButton的樣式,而第二條語句表示在myPushButton對象上設置樣式。最終結果會將myPushButton的前景顏色設置為藍色。級聯(lián)效果主要應用在當一個控件的樣式在多個容器控件上都有設置的時候,該控件的最終效果是這些所有容器控件上效果的合并。級聯(lián)規(guī)則在CSS中本身也是一個復雜的主題,如果大家感興趣,還是需要自己參考CSS2的規(guī)范文檔,本節(jié)僅僅是拋裝引玉。
另外一個要提到的是,QSS中似乎為父容器控件本身設置的樣式,并不會被子控件繼承,例如如果QFrame中有一個QPushButton控件,那么如下的語句:
ui->frame->setStyleSheet("QFrame{ color: red; border:1px solid red }");
該語句僅僅為QFrame設置前景顏色以及邊框的效果并不會應用到其里面的QPushButton上,如果是下面的語句則都可以:
ui->frame->setStyleSheet("QPushButton{ color: red; border:1px solid red }");
ui->frame->setStyleSheet("*{ color: red; border:1px solid red }");
QSS實際應用中要注意的地方
在使用QSS的時候遇到過一些坑,看似簡單,但是如果不知道的話,還是很折磨人的:
<1>使用QSS設置邊框無效,例如:
border:1px solid red; //Ok
border:solid 1px red; //Error
border:red 1px solid; //Error
border:red solid 1px; //Error
設置邊框顏色和像素的時候,必須是第一種順序,而CSS中是無所謂的,至于原因,我也不清楚,就是這么坑人。
<2> QSS設置寬高無效:
在QSS中設置寬高必須要使用 min-width和min-height,max-width,max-height來設置,用width和height設置是沒有任何效果的。
<3>QComboBox的樣式設置的問題:
QcomboBox是一個復雜的控件,QComboBox由3部分組成,一個是QComboBox的外框,里面有一個下拉按鈕,這個按鈕可以通過QComboBox::drop-down 來控制其位置,將其定義到QComboBox的左邊而不一定是右邊。另外在這個下拉按鈕上面一般會有一個向下的箭頭,這個箭頭圖像也是可以定制的,通過QComboBox::down-arrow來指定箭頭的圖像。
如果要控制QComboBox的彈出下拉列表的樣式需要通過:
QComboBox QAbstractItemView {//設置當點擊下拉按鈕之后彈出的下拉列表的樣式,要注意的是這里的樣式//僅僅只能設置彈出的整個下拉列表范圍的矩形的樣式,不能設置下拉列表//中的每一個下拉項的樣式,例如不能設置每一個下拉項高度
}
QcomboBox{//設置未彈出下拉列表的樣式
}QComboBox QAbstractItemView::item {
//設置彈出下拉列表中的每一個下拉項的樣式,這里的樣式要想生效,必須先
//對QcomboBox做下面的設置
//QStyledItemDelegate* itemDelegate = new QStyledItemDelegate();
//combox->setItemDelegate(itemDelegate);
}