溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

QT開發(fā)(六十四)——QT樣式表(一)

發(fā)布時(shí)間:2020-09-26 09:29:42 來源:網(wǎng)絡(luò) 閱讀:20303 作者:天山老妖S 欄目:開發(fā)技術(shù)

QT開發(fā)(六十四)——QT樣式表

    本文主要翻譯自QT官方文檔Qt Style Sheets

一、QT樣式表簡介

1QT樣式表簡介

    QSS的主要功能是使界面的表現(xiàn)與界面的元素分離,使得設(shè)計(jì)皮膚與界面控件分離的軟件成為可能

QT樣式表是允許用戶定制widgets組件外觀的強(qiáng)大機(jī)制,此外,子類化QStyle也可以定制widgets組件外觀。QT樣式表的概念、術(shù)語、語法很大程度上受到了CSS層疊樣式表的影響。

樣式表是使用QApplication::setStyleSheet()設(shè)置在應(yīng)用程序或是使用QWidget::setStyleSheet()設(shè)置在具體組件及其子對(duì)象的文字說明。

例如,以下樣式表指明QLineEdit使用×××作為背景色,QCheckBox使用紅色作為文本顏色。

    QLineEdit { background: yellow }

    QCheckBox { color: red }

    對(duì)于這種定制,樣式表比QPalette更強(qiáng)大。例如,要獲取一個(gè)紅色的按鈕,可以設(shè)置QPushButton的QPalette::Button角色為紅色。然而,這并不保證對(duì)所有的樣式有效,因?yàn)闃邮降臉?gòu)造者會(huì)被不同平臺(tái)的原則和本地的主題引擎所限制。

    樣式表可以實(shí)現(xiàn)那些很難或是不可能使用QPalette實(shí)現(xiàn)的所有定制。

    如果想要某些強(qiáng)制字段為×××背景,按鈕為紅色文字,或是絢麗的復(fù)選框,樣式表可以完成。

2、QT樣式表編程

A、在代碼中直接設(shè)置QSS

    QPushButton *button = new QPushButton(this);

    button->setText("hello");

    button->setStyleSheet("QPushButton{background-color:red; color:blue}");

B、通過文件設(shè)置QSS

QSS代碼寫入.qss文件

.qss文件加入資源文件qrc.qrc中

在代碼中讀取QSS文件設(shè)置組件QSS

    QPushButton *button = new QPushButton(this);

    button->setText("hello");

    QFile file(":/qss/dev.qss");

    file.open(QIODevice::ReadOnly);

    QString stylesheet = QLatin1String(file.readAll());

    button->setStyleSheet(stylesheet);

    file.close();

 

二、QT樣式表語法

QT樣式表的術(shù)語和語法規(guī)則與HTML CSS很相似。

1、樣式規(guī)則

樣式表由樣式規(guī)則序列組成。樣式規(guī)則由選擇器和聲明組成。選擇器指定了那些組件受規(guī)則影響,聲明指定了組件設(shè)置了哪些屬性。例如:

    QPushButton { color: red }

以上樣式規(guī)則中,QPushButton是選擇器,{ color: red }是聲明。樣式規(guī)則指定了QPushButton及其子類應(yīng)使用紅色作為前景色。

QT樣式表大小寫不敏感,除了類名、對(duì)象名、QT屬性名是大小寫敏感的。

多個(gè)選擇器可以指定同一個(gè)聲明,使用逗號(hào)分隔選擇器。例如以下規(guī)則:

    QPushButton, QLineEdit, QComboBox { color: red }

等效于三個(gè)規(guī)則:

    QPushButton { color: red }

    QLineEdit { color: red }

    QComboBox { color: red }

樣式規(guī)則的聲明部分是一個(gè)“屬性:值”對(duì)的鏈表。聲明部分在{}內(nèi),不同的屬性:值”對(duì)使用分號(hào)分隔。例如:

    QPushButton { color: red; background-color: white }

2、選擇器的類型

到目前為止所有的例子使用的都是最簡單的選擇器類型。QT樣式表支持CSS2定義的所有選擇器。下表總結(jié)了最常用的選擇器類型。

選擇器

示例

說明

通用選擇器

*

匹配所有的組件

類型選擇器

QPushButton

匹配所有QPushButton機(jī)器子類的實(shí)例

屬性選擇器

QPushButton[flat="false"]

匹配所有QPushButton屬性flat為false的實(shí)例。屬性分為靜態(tài)屬性和動(dòng)態(tài)屬性,靜態(tài)屬性可以通過Q_PROPERTY()來指定,動(dòng)態(tài)屬性可以使用setProperty來指定。

類選擇器

.QPushButton

匹配QPushButton的實(shí)例,子類除外

ID選擇器

QPushButton#okButton

匹配對(duì)象名為okButton的所有QPushButton實(shí)例

 

后代選擇器

QDialog QPushButton

匹配QDialog后代的所有QPushButton實(shí)例

子選擇器

QDialog > QPushButton

匹配QDialog子類對(duì)象QPushButton的所有實(shí)例

3、子控件選擇器

對(duì)于樣式復(fù)雜的組件,需要訪問組件的子控件,如QComboBox的下拉按鈕或QSpinBox的上下箭頭。選擇可以包含子控件來對(duì)組件的特定子控件應(yīng)用規(guī)則。

    QComboBox::drop-down { p_w_picpath: url(dropdown.png) }

以上規(guī)則會(huì)對(duì)所有QComboBox的下拉框應(yīng)用樣式規(guī)則。盡管雙冒號(hào)::很像CSS3的偽元素,但QT子控件選擇器在概念上是不同的,有不同的級(jí)聯(lián)語義。

子控件選擇器通常根據(jù)另一個(gè)參考元素進(jìn)行定位。參考元素可以是組件或是另一個(gè)子控件選擇器。例如,QComboBox的::drop-down默認(rèn)放置在QComboBox襯底矩形的右上角。::drop-down默認(rèn)放置在::drop-down子控件選擇器的內(nèi)容矩形的中心。

可以使用subcontrol-origin屬性改變原點(diǎn)矩形。例如,如果想要將drop-down放置在邊界矩形而不是默認(rèn)的襯底矩形,可以指定:

    QComboBox {

      margin-right: 20px;

  }

  QComboBox::drop-down {

      subcontrol-origin: margin;

  }

drop-down在邊界矩形內(nèi)的對(duì)齊方式通過subcontrol-position屬性改變。寬屬性和高屬性用于控制子控件選擇器的大小。注意,設(shè)置一幅圖片會(huì)隱式地設(shè)置子控件選擇器的大小。

相對(duì)定位方法(positionrelative)允許子控件選擇器的位置偏離它原來的位置。例如,當(dāng)QComboBox的下拉按鈕按下,想要一種被按下的效果可以通過指定如下實(shí)現(xiàn):

    QComboBox::down-arrow {

          p_w_picpath: url(down_arrow.png);

      }

      QComboBox::down-arrow:pressed {

          position: relative;

          top: 1px; left: 1px;

      }

絕對(duì)定位方法(positionabsolute)允許子控件選擇器的位置和大小的改變與參考元素有關(guān)。

一旦定位,就可以像組件那樣使用盒子模型對(duì)其進(jìn)行造型。

注意,像QComboBoxQScrollBar這樣復(fù)雜的組件,如果有一個(gè)屬性或是子控件選擇器被定制,所有其他的屬性或是子控件選擇器也要必須被定制。

常用輔助控制器:

::indicator              單選框、復(fù)選框、可選菜單項(xiàng)或可選群組項(xiàng)的指示器  

::menu-indicator         按鈕的菜單指示器  

::item                   菜單、菜單欄或狀態(tài)欄項(xiàng)  

::up-button              微調(diào)框或滾動(dòng)條的向下按鈕  

::down-button            微調(diào)框或滾動(dòng)條的向上按鈕  

::up-arrow               微調(diào)框、滾動(dòng)條或標(biāo)題視圖的向上按鈕  

::down-arrow             微調(diào)框、滾動(dòng)條或標(biāo)題視圖的向下按鈕  

::drop-down              組合框的下拉箭頭  

::title                  群組框的標(biāo)題

4、偽選擇器

選擇器可能包含限制基于組件狀態(tài)的規(guī)則應(yīng)用的偽狀態(tài)。偽狀態(tài)出現(xiàn)在選擇器的尾部,中間使用分號(hào)連接。例如,以下規(guī)則用于鼠標(biāo)懸停在一個(gè)QPushButton上:

    QPushButton:hover { color: white }

偽狀態(tài)可以使用嘆號(hào)取反,例如,以下規(guī)則用于鼠標(biāo)不懸停在QRadioButton:

    QRadioButton:!hover { color: red }

偽狀態(tài)可以以邏輯與的方式連接使用,例如,以下規(guī)則應(yīng)用于鼠標(biāo)懸停在一個(gè)選中的QCheckBox上:

    QCheckBox:hover:checked { color: white }

取反偽狀態(tài)可以出現(xiàn)在偽狀態(tài)鏈中。例如,以下規(guī)則用于鼠標(biāo)懸停在一個(gè)QPsuButton上,但沒有按下:

    QPushButton:hover:!pressed { color: blue; }

    如果需要,使用逗號(hào)可以將偽狀態(tài)以邏輯或連接。

    QCheckBox:hover, QCheckBox:checked { color: white }

    偽狀態(tài)可以結(jié)合子控件選擇器使用:

    QComboBox::drop-down:hover { p_w_picpath: url(dropdown_bright.png) }

常用狀態(tài):

:disabled                   禁用的窗口部件  

:enabled                    啟用的窗口部件  

:focus                      窗口部件有輸入焦點(diǎn)  

:hover                      鼠標(biāo)在窗口部件上懸停  

:pressed                    鼠標(biāo)按鍵點(diǎn)擊窗口部件  

:checked                    按鈕已被選中  

:unchecked                  按鈕未被選中  

:indeterminate              按鈕被部分選中  

:open                       窗口部件處于打開或擴(kuò)展的狀態(tài)  

:closed                     窗口部件處于關(guān)閉或銷毀狀態(tài)  

:on                         窗口部件的狀態(tài)是on  

:off                        窗口部件的狀態(tài)是on  

5、沖突處理

當(dāng)多個(gè)樣式規(guī)則使用多個(gè)值指定同一個(gè)屬性時(shí)會(huì)產(chǎn)生沖突。

    QPushButton#okButton { color: gray }

    QPushButton { color: red }

    以上兩條規(guī)則匹配名為okButtonQPushButton實(shí)例,在color屬性上有沖突。為了解決沖突,需要考慮選擇器的特征。上例中,QPushButton#okButtonQPushButton要更具體,因?yàn)?/span>QPushButton#okButton指向單個(gè)的對(duì)象,而不是類的所有實(shí)例。

類似,偽選擇器比未指定偽狀態(tài)的選擇器更具體。因而,以下樣式表指定,當(dāng)鼠標(biāo)懸停在QPushButton上時(shí),QPushButton的文本為白色,否則為紅色。

    QPushButton:hover { color: white }

    QPushButton { color: red }

    嚴(yán)謹(jǐn)一點(diǎn)應(yīng)該是:

    QPushButton:hover { color: white }

    QPushButton:enabled { color: red }

    如果鼠標(biāo)懸停在按鈕上,兩個(gè)選擇器有相同的特性,則第二條規(guī)則優(yōu)先。如果想要文本為白色,需要重新排序規(guī)則:

    QPushButton:enabled { color: red }

    QPushButton:hover { color: white }

    或者,可以使第一條規(guī)則更加具體:

    QPushButton:hover:enabled { color: white }

    QPushButton:enabled { color: red }

    和類型選擇器一起使用時(shí),類似的問題也會(huì)發(fā)生

    QPushButton { color: red }

    QAbstractButton { color: gray }

    以上兩條規(guī)則用于QPushButton實(shí)例(由于QPushButton繼承自QAbstractButton),并有color屬性的沖突。由于QPushButton繼承自QAbstractButton,所以會(huì)假設(shè)QPushButtonQAbstractButton更具體。然而,對(duì)于樣式表的計(jì)算,所有的類型選擇器有相同的特性,最后出現(xiàn)的規(guī)則優(yōu)先。換句話說,所有的QAbstractButtoncolor屬性會(huì)被設(shè)置為gray,包括QPushButton。如果真的想要QPushButton的文本為red,通常會(huì)重新排序規(guī)則。

    為了確定規(guī)則的特性,QT樣式表遵循CSS2規(guī)范:

    選擇器特性的計(jì)算方法如下:

    計(jì)算選擇器中ID屬性的數(shù)量(=a)

    計(jì)算選擇器中其他屬性和偽狀態(tài)類的數(shù)量(=b)

    計(jì)算選擇器中元素的數(shù)量(=c)

    忽略偽元素(如子控件選擇器)

    串聯(lián)的三個(gè)數(shù)字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 */

6、級(jí)聯(lián)

QT樣式表可以設(shè)置在應(yīng)用程序、父組件、子組件上。通過合并組件的祖先(父親、祖父等)可以獲取任意組件的有效樣式表,以及設(shè)置在應(yīng)用程序上的任何樣式表。

沖突發(fā)生時(shí),不論沖突規(guī)則的特性如何,組件自己的樣式表總是優(yōu)先于任何繼承而來的樣式表。同樣,父組件的樣式表優(yōu)先于祖父組件的樣式表。

這樣的結(jié)果是,在一個(gè)組件上設(shè)置樣式規(guī)則會(huì)自動(dòng)獲得比祖先組件的樣式表或是應(yīng)用程序的樣式表指定的其他規(guī)則更高的優(yōu)先級(jí)。例如,首先在應(yīng)用程序設(shè)置樣式表

    qApp->setStyleSheet("QPushButton { color: white }");

然后,在QPushButton對(duì)象設(shè)置一個(gè)樣式表

    myPushButton->setStyleSheet("* { color: blue }");

QPushButton的樣式表會(huì)強(qiáng)制QPushButton(及其任何子組件)顯示藍(lán)色文本,盡管應(yīng)用程序范圍的樣式表提供了更具體的規(guī)則。

下列寫法也會(huì)得到相同的結(jié)果:

    myPushButton->setStyleSheet("color: blue");

但如果QPushButton有子組件,樣式表不會(huì)對(duì)子組件有效果。

樣式表級(jí)聯(lián)是一個(gè)復(fù)雜的主題,更詳細(xì)的內(nèi)容請參考CSS2規(guī)范。QT目前沒有實(shí)現(xiàn)。

7、繼承

在經(jīng)典的CSS中,當(dāng)元素的字體和顏色沒有顯示設(shè)置時(shí),會(huì)自動(dòng)從父組件繼承。使用QT樣式表時(shí),一個(gè)組件不會(huì)自動(dòng)繼承父組件設(shè)置的字體和顏色。例如,一個(gè)QGroupBox包含一個(gè)QPushButton:

    qApp->setStyleSheet("QGroupBox { color: red; } ");

QPushButton并沒有顯示設(shè)置顏色,因此并不是繼承父組件QGroupBox的顏色,而是擁有系統(tǒng)的顏色。如果要設(shè)置QGroupBox及其子組件的顏色,如下:

    qApp->setStyleSheet("QGroupBox, QGroupBox * { color: red; }");

相比之下,使用QWidget::setFont() 和 QWidget::setPalette()為子組件設(shè)置字體和畫板。

8、C++命名空間內(nèi)部的組件

類型選擇器特殊類型的組件的樣式定制。例如:

class MyPushButton : public QPushButton {

      // ...

  }

  // ...

  qApp->setStyleSheet("MyPushButton { background: yellow; }");

    QT樣式表使用組件的QObject::className() 確定何時(shí)應(yīng)選擇器。當(dāng)自定義組件在命名空間內(nèi)部時(shí),QObject::className()會(huì)返回<namespace>::<classname>。這會(huì)與子控件選擇器的語法產(chǎn)生沖突。為了解決這個(gè)問題,當(dāng)在命名空間內(nèi)使用組件的類型選擇器時(shí),必須使用--”代替“::”。

namespace ns {

      class MyPushButton : public QPushButton {

          // ...

      }

  }

  // ...

  qApp->setStyleSheet("ns--MyPushButton { background: yellow; }");

9、設(shè)置QObject屬性

QT4.3開始,任何可被設(shè)計(jì)的Q_PROPERTY都可以使用qproperty-<property name>語法設(shè)置。

MyLabel { qproperty-pixmap: url(pixmap.png); }

MyGroupBox { qproperty-titleColor: rgb(100, 200, 100); }

QPushButton { qproperty-iconSize: 20px 20px; }

如果屬性引用了Q_ENUMS聲明的枚舉,應(yīng)該通過名字引用常量值,而不是數(shù)字。

三、QT設(shè)計(jì)器中的樣式表

    Qt Designer是一款預(yù)覽樣式表的優(yōu)秀工具,右擊設(shè)計(jì)器中的任何組件,選擇Change styleSheet...可以設(shè)置樣式表。

    QT4.2開始,Qt Designer包含了一個(gè)樣式表語法高亮器和驗(yàn)證器。如果語法合法或非法,驗(yàn)證器可以在Edit Style Sheet對(duì)話框的左下角指示。

QT開發(fā)(六十四)——QT樣式表(一)

    當(dāng)點(diǎn)擊Ok或Apply按鈕時(shí),Qt Designer會(huì)自動(dòng)使用新樣式表顯示組件。

四、使用樣式表定制QT組件

當(dāng)使用樣式表時(shí),每個(gè)組件會(huì)被當(dāng)作有四個(gè)同心矩形:空白矩形、邊界矩形、襯底矩形、內(nèi)容矩形的盒子。

1、盒子模型

四個(gè)同心矩形如下所示:

QT開發(fā)(六十四)——QT樣式表(一)

    margin, border-width,padding屬性默認(rèn)都是0。此時(shí)四個(gè)矩形完全相同。

    可以使用background-p_w_picpath屬性指定組件的背景。默認(rèn),background-p_w_picpath只會(huì)在邊界矩形內(nèi)被繪制,使用background-clip屬性可以修改。使用background-repeat屬性background-origin屬性來控制背景圖片的重復(fù)和來源。

    background-p_w_picpath屬性不會(huì)縮放組件的大小。為了提供隨著組件大小縮放的皮膚或背景,必須使用border-p_w_picpath屬性。由于border-p_w_picpath屬性提供了一個(gè)可選擇的背景,當(dāng)指定border-p_w_picpath屬性時(shí),不會(huì)要求指定background-p_w_picpath屬性。當(dāng)background-p_w_picpath屬性和border-p_w_picpath屬性都被指定時(shí),border-p_w_picpath屬性會(huì)被繪制在background-p_w_picpath屬性之上。

    此外,p_w_picpath屬性可以用于在border-p_w_picpath屬性上繪制一幅圖像。當(dāng)組件的大小與p_w_picpath的大小不匹配時(shí),指定的p_w_picpath不會(huì)伸縮,對(duì)齊方式可以使用p_w_picpath-position屬性設(shè)置。與background-p_w_picpath屬性和border-p_w_picpath屬性不同,p_w_picpath屬性可以指定SVG,使p_w_picpath根據(jù)組件的大小自動(dòng)縮放。

    渲染規(guī)則的步驟如下:

    A、為整個(gè)渲染操作設(shè)置clip(border-radius

    B、繪制背景(background-p_w_picpath

 C、繪制邊界(border-p_w_picpath,border)

 D、繪制覆蓋圖像(p_w_picpath)

2、子控件

一個(gè)組件可以看作一顆子控件樹。例如QComboBox繪制下拉按鈕子控件,下拉按鈕子控件繪制了向下箭頭子控件。

    子控件享有父子關(guān)系。QComboBox中,向下箭頭的父親是下拉按鈕,下拉按鈕的父親的QComboBox組件本身。子控件可以使用subcontrol-position熟悉subcontrol-origin屬性定位在父組件內(nèi)。

    一旦定位,子控件就可以使用盒子模型定制樣式。

注意,像QComboBoxQScrollBar這樣復(fù)雜的組件,如果有一個(gè)屬性或是子控件選擇器被定制,所有其他的屬性或是子控件選擇器也要必須被定制。




向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI