QSS稱爲Qt Style Sheets也就是Qt樣式表,它是Qt提供的一種用來自定義控件外觀的機制。QSS大量參考了CSS的內容,只不過QSS的功能比CSS要弱不少,體如今選擇器要少,可使用的QSS屬性也要少不少,而且並非全部的屬性均可以用在Qt的全部控件上。web
首先將QSS寫在文件中,而後利用以下的代碼設置QSS:app
MainWidget::MainWidget(QWidget *parent) : QWidget(parent), ui(new Ui::MainWidget) { //應用樣式 apply the qss style QFile file(":/qss/main.qss"); file.open(QFile::ReadOnly); QTextStream filetext(&file); QString stylesheet = filetext.readAll(); this->setStyleSheet(stylesheet); file.close(); }
該段代碼寫在ui界面的後臺cpp文件的構造函數中,主要是this->setStyleSheet()函數的設置功能,要說明的是該函數除了能夠對整個當前構造數所在的那個類所表示的ui進行總體應用樣式之外,setStyleSheet()函數自己是QWidget的成員函數,幾乎Qt中的大多數控件均可以直接使用該函數分別設置本身的樣式。函數
QSS的語法規則幾乎與CSS相同。一條QSS的樣式是由兩部分組成的,一部分是選擇器指定了哪些控件會受到影響,另外一部分是指定了屬性的值,表示這些控件的哪些屬性會受到影響。例如:工具
QPushButton { color: red }
QPushButton表示選擇器,指定了全部的QPushButton或者是QPushButton的子類會受到影響,注意凡是繼承自QPushButton的子類也會受到影響,這是與CSS中不一樣的地方,由於CSS應用的都是一些標籤,沒有類的層次結構,更加沒有子類的概念。然後面的{color:red}則是規則的定義,代表指定前景顏色是紅色。整個意思就是設置QPushButton類以及其子類的全部實例的前景色是紅色。
若是MyButton繼承自QPushButton,那麼上面的規則也會應用到全部MyButton控件上,可是若是規則是以下的:ui
MyButton{color:red}
則只會對MyButton的實例應用紅色的前景顏色,而對QPushButton的實例沒有應用。this
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的直接父容器是QDialogurl
另外上面全部的這些選擇器能夠聯合使用,而且支持一次設置多個選擇器類型,用逗號隔開,這點與CSS同樣,例如#frameCut,#frameInterrupt,#frameJoin 表示全部這些id使用一個規則。#mytable QPushButton 表示選擇全部id爲mytable的容器下面的QPushButton實例spa
QSS的子控件實際上也是選擇器的一種,由於這種選擇器與CSS有一些不一樣,因此單獨拿出來講,QSS的子控件選擇器是應用在一些複合控件上的,典型的例如QComboBox,該控件的外觀包含幾個部分,通常狀況下有一個矩形的外邊框,右邊有一個向下的箭頭用於提示點擊以後會有彈出下拉列表。例如:code
QComboBox::drop-down { image: url(dropdown.png) }
上面的樣式指定全部QComboBox的下拉箭頭的圖片爲自定義的圖片dropdown.png
::dropdown子控件選擇器也能夠與上面提到的選擇器一塊兒聯合使用:視頻
QComboBox#myQComboBox::drop-down { image: url(dropdown.png) }
指定id名爲myQComboBox的QComboBox控件的下拉箭頭的自定義圖片,要注意的是子控件選擇器其實是選擇複合控件中的一部分,也就是說對複合控件中的一部分應用樣式,例如爲QComboBox的下拉箭頭指定圖片,而不是爲QComboBox自己指定圖片。
QSS爲不少複雜的複合控件提供了子控件的定義,以方便對這些複合控件的各個部分進行樣式設置。限於篇幅,本文也不能將這些可用的子控件都列出來,在安裝QtCreator以後自帶的幫助中就有很詳細的描述。
QSS的僞狀態選擇器實際上與CSS中的相似,是以冒號開頭的一個選擇表達式,例如:hover表示當鼠標通過時候的狀態。他限制了當控件在某一種狀態下的時候才能應用QSS規則,僞狀態只能描述一個控件的狀態,或者是一個複合控件中的子控件的狀態,因此該僞狀態選擇器只能放在選擇器的最後面,例如:
QComboBox:hover{background-color:red;}
該規則表示當鼠標通過QComboBox上面的時候,其背景顏色指定爲紅色,該僞狀態 :hover描述的是QComboBox的狀態。
僞狀態除了描述選擇器選擇的控件之外,還能夠描述子控件選擇器所選擇的複合控件中的子控件的狀態,例如:
QComboBox::drop-down:hover{background-color:red;}
表示當鼠標通過QComboBox的下拉箭頭的時候,該下拉箭頭的背景顏色變成紅色。
此外僞狀態能夠用一個感嘆號表示否,例如:hover表示鼠標通過,而:!hover表示鼠標沒有通過的狀態。幾個僞狀態能夠同時一塊兒使用,例如:
QCheckBox:hover:checked { color: white }
指定一個當鼠標通過一個選中的QCheckBox的時候,設置其文字的前景顏色爲白色。
QSS提供了不少的僞狀態,一些僞狀態只能用在特定的控件上,具體有哪些僞狀態,在Qt的幫助裏面有詳細的列表,限於篇幅這裏也不列出了。
QSS中的級聯包含幾個方面的概念,一個是當在同一個控件上應用兩個不一樣的規則,那麼應該應用哪個規則的問題,也就是如何解決這種衝突。二個是在一個容器控件上設置的QSS規則會對容器裏面的控件產生效果(這要取決於容器控件上設置的QSS規則是什麼樣的規則,若是容器控件上設置的QSS規則僅僅針對容器控件自己則該規則對子控件沒有影響,若是該QSS規則裏面有對子控件的設置,則天然會對子控件產生效果),級聯問題是解決當一個控件被層層父容器包裹,而且在每一層的父容器上都有對該控件的樣式設置的時候,該控件的最終效果是合併這些父容器上的QSS效果。
衝突問題:
QPushButton#okButton { color: gray } QPushButton { color: red }
這兩條規則都會應用到名爲okButton的按鈕上,可是他們爲同一個屬性設置了不一樣的顏色,這會有衝突,那麼要解決這樣的衝突就必須考慮到選擇器的特異性(這個詞怎麼理解,我理解爲這個特異性爲更加特殊,實際上CSS上用權重表示這裏的特異性),顯然QPushButton#okButton僅僅針對對象名爲okButton的控件有效果,而QPushButton卻對全部的QPushButton的實例或者是其子類的實例有效果,顯然QPushButton#okButton選擇器更加特殊,也就是更具備特異性。因此最終okButton前景色被應用爲灰色。若是兩條規則的特異性同樣,那麼就選擇放在後面的那一條。
另外若是一個選擇器應用了僞狀態,而另外一個沒有,那麼應用了僞狀態的選擇器要更加特殊,例如:
QPushButton:hover { color: white } QPushButton { color: red }
顯然QPushButton:hover比單純的QPushButton更加具備特異性。這兩條規則表示當鼠標放在按鈕上的時候文字是白色,其餘狀況下都是紅色。
以下面兩個規則的特異性是同樣的,那麼應該是如何應用呢:
QPushButton:hover { color: white } //若是鼠標通過則前景白色 QPushButton:enabled { color: red } //若是按鈕是enabled狀態則前景紅色
因此默認狀況下前景文字是紅色的,當鼠標通過的時候並不會變成白色,由於他們的特異性是同樣的,因此選擇後面的,也就是紅色。
那麼換一下順序會怎樣呢:
QPushButton:enabled { color: red } //若是按鈕是enabled狀態則前景紅色 QPushButton:hover { color: white } //若是鼠標通過則前景白色
當鼠標通過的時候,就變成白色的了,由於他們的特異性同樣,因此選擇後面的規則,也就是鼠標通過前景變成白色。
若是把其中的一條的特異性增長,例如:
QPushButton:hover:enabled { color: white } QPushButton:enabled { color: red }
那麼第一條的特異性比第二條大,因此應用第一條的規則。
另一種特異性發生在類型選擇器上:
QPushButton { color: red } //應用在全部的QPushButton上 QAbstractButton { color: gray } //應用在全部的QAbstractButton上
而在類的繼承結構上,QAbstractButton是QPushButton的父類,顯然QPushButton更加具備特異性,因此QPushButton的前景顏色被應用爲紅色,而不是灰色。有沒有一個辦法來肯定兩條QSS規則的特異性大小呢,其實QSS使用的特異性的計算方法與CSS是同樣的,詳細能夠參考CSS2的文檔規範,這裏仍是簡要的說明一下,特異性這個東西在CSS中通常被稱爲權重,權重越大的越優先使用,CSS的計算規則以下:
1.計算一條規則中id選擇器的個數,假設存放在變量a中
2.計算一條規則中類選擇器和屬性選擇器的個數,存放在變量b中
3.計算一條規則中的類型選擇器的個數,存放在變量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 */
上面的計算規則是CSS的計算規則,一樣能夠應用的QSS上。
關於級聯:
QSS能夠設置在QApplication上,也能夠設置在一個部件的容器部件上,也能夠設置在子孫部件上,一個部件最終使用的樣式效果是合併了他的全部父容器,祖父容器等上面設置的全部樣式的結果,這些設置會進行疊加。若是在級聯過程當中發生了衝突,例如部件自己指定的前景顏色爲綠色,而其父親容器爲其指定的前景顏色爲紅色,此時就選擇部件自己設置的樣式效果。例如:
qApplication->setStyleSheet("QPushButton { color: white }"); myPushButton->setStyleSheet("* { color: blue }");
第一條語句表示在QApplication上設置QPushButton的樣式,而第二條語句表示在myPushButton對象上設置樣式。最終結果會將myPushButton的前景顏色設置爲藍色。級聯效果主要應用在當一個控件的樣式在多個容器控件上都有設置的時候,該控件的最終效果是這些全部容器控件上效果的合併。級聯規則在CSS中自己也是一個複雜的主題,若是你們感興趣,仍是須要本身參考CSS2的規範文檔,本節僅僅是拋裝引玉。
另一個要提到的是,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的時候遇到過一些坑,看似簡單,可是若是不知道的話,仍是很折磨人的:
<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); }
前面一段時間用Qt開發了一個基於公司平臺的視頻導出與編輯工具,看成一個案例貼出來吧,仍是有不少能夠美化的地方,窗體的外框沒有作任何美化處理,用QSS作起來其實仍是蠻簡單的,裏面的頁面按鈕,文本框,分頁功能等都用QSS設置過,其實這個軟件的界面算是中規中矩的,要作成酷狗,360那種風格用QSS是徹底沒有問題的:
登陸界面,裏面用到了Qt提供的正則驗證功能,若是輸入的ip不符合規則,則根本輸入不了,例如若是輸入一個非法的字符,則文本框中沒有反應
登陸進去以後的主界面,一共有7個選項卡,每個選項卡表明一個功能:
視頻導出:導出web平臺上的視頻數據,包括文件,片頭片尾,視頻的索引,能夠導出電影模式,資源模式,支持斷點續傳。
視頻剪切:能夠將視頻中不須要的內容剪切掉
視頻截取:截取視頻中須要的部分
後期導播:對資源模式進行後期導播
建立片頭片尾:傻瓜式的生成片頭片尾的圖片文件
合成片頭片尾:將片頭片尾的圖片文件添加到一個視頻的起始和結束
轉碼上傳:將多種格式的視頻文件轉碼成MP4文件並上傳到web平臺
視頻導出功能,其實是導出一個課件,該課件可能錄製的有電影模式的視頻,資源模式的視頻,或者都有。功能介紹以下:
視頻剪切對視頻進行剪切處理:
對視頻進行截取:
對資源模式進行後期導播:
建立自定義片頭片尾(其實就是傻瓜式的讓用戶生成自定義圖片),裏面的文字能夠拖動,能夠鍵盤微調,能夠修改:
合併片頭片尾,將生成好的片頭片尾圖片,合併到一個mp4的開始和結尾處,能夠指定片頭片尾的圖片文件,並指定在mp4開頭或結尾顯示的時間:
轉碼與上傳:
程序裏面的外觀包括,下拉列表,文本輸入框,按鈕,表格,tab等都是使用QSS設置的。QSS參考了CSS,全部裏面有一些屬性是與CSS相同的,但並非全部的CSS屬性都可以在QSS中使用,也並非全部的Qt控件都支持CSS的盒模型,Qt幫助中關於QSS的部分詳細描述了可用的QSS屬性列表,以及控件列表,僞狀態列表,子控件列表,QSS中可用的圖標列表,以及QSS屬性值的單位列表,限於篇幅不可能將全部這些都詳細列出來,其實在安裝QtCreator以後的幫助文檔中有詳細的描述,其列表相似下面的圖(描述了部分僞狀態的說明):