Qt 外觀之一 ——Qt Style Sheet


Qt Style Sheet

 

目錄

使用

對於應用程序

創建自定義控件

QSS語法

一般選擇器(selector)

偽選擇器

解決沖突

使用specificity

Namespace沖突

級聯效應

設置對象屬性

comments

STYLE基礎知識的說明

CSS 背景屬性(Background)

CSS 邊框屬性(Border 和 Outline)

Box 屬性

CSS 字體屬性(Font)

CSS 外邊距屬性(Margin)

CSS 內邊距屬性(Padding)

CSS 定位屬性(Positioning)

CSS 文本屬性(Text)

 

 

借用css 的靈感, Qt也支持Qt自己的css, 簡稱qss。同css 相似,qss的主要功能與最終目的都是能使界面的表現與界面的元素分離,即質與形的分離,就如同一個人可以在不同的時候穿上不同的衣服一樣,css機制的引入,使得設計一種皮膚與界面控件分離的軟件成為可能,應用程序也能像web界面那樣隨意地改變外觀。

               

使用

對於應用程序

特定應用的QSS效果可以使用命令-styele定制,也可以使用 QApplication::setStyle()定義。 特定的widgets 可以使用  QWidget::setStyle() 定義。   

創建自定義控件

在Widget的paint方法里使用 QStyle::drawItemText(pixmap...), 可以以一些格式繪制文字、圖片等, 相對於使用QPainter, 簡單許多。

例如, 使用 Delegate 繪制QQ 好友列表(Model View 略)

void ShareeSignatureDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const

{

// 沿用父類的繪制效果

QStyledItemDelegate::paint(painter, option, index);

   

painter->save();

   

// modedata接口里根據role獲取姓名和簽名內容(NameRole,SignatureRoledata接口里自定義的角色名)

QString sharerName = index.data(NameRole).toString();

QString signature = index.data(SignatureRole).toString();

   

QStyleOptionViewItemV4 optV4 = option;

initStyleOption(&optV4, index);

const QWidget *widget = optV4.widget;

QStyle *style = widget ? widget->style() : QApplication::style();

   

QRect rect = style->subElementRect(QStyle::SE_ItemViewItemText, &optV4, widget);

   

// 定義起始位置

rect = rect.adjusted(5, 0, 0, - optV4.rect.height() / 2);

   

// 設置文字的長度,以及文字過長時的省略模式

QFontMetrics fontMetrics = painter->fontMetrics();

QString elidedNameLine = fontMetrics.elidedText(sharerName, Qt::ElideMiddle, rect.width());

QString elidedSignatureLine = fontMetrics.elidedText(signature, Qt::ElideMiddle, rect.width());

   

// 執行文字繪制

style->drawItemText(painter, rect, Qt::AlignBottom, QApplication::palette(), true, elidedNameLine);

// 設置簽名內容的位置,使得該內容在姓名的下方

rect.moveTop(rect.bottom());

painter->setPen(QColor("#949fa5"));

if(!signature.isEmpty())

style->drawItemText(painter, rect, Qt::AlignVCenter, QApplication::palette(), true, elidedSignatureLine);

else

style->drawItemText(painter, rect, Qt::AlignVCenter, QApplication::palette(), true, "T???息¢");

   

painter->restore();

}

 

QWidget 的繪制使用雙緩沖技術, 即, 前景與背景分離, 所以可以根據自己的需要僅僅定制前景或者背景。 也可以定義自己QPalette, 並且制定它的PaletteRole,Widgets 使用雙緩沖技術繪制, 可以固定前景去修改背景, 也可以固定背景去修改前景。 對於實時性要求比較高、繪制量大的系統, 例如 圖表 和 曲線, 可以使用 palette 設定背景,然后在 paintEvent 里面繪制關注的內容即可。 palette的繪制會先於paintEvent, 而且 palette 使用 Implicit Sharing, 它的使用比較有效。 

this->setBackgroundRole( QPalette::Window);

this->setAutoFillBackground(true);

   

QPalette palette (this->palette());

palette.setColor(QPalette::Background, Qt::black);

this->setPalette( palette );

/*

重寫 paintEvent

*/

 

QSS語法

同css一樣,他也有由一個selector與一個declaration組成,selector指定了是對哪一個控件產生效果,而declaration才是真正的產生作用的語句。如:
QPushButton { color: red }
QPushButton指定了是對所有的QPushButton或是其子類控件(如用戶定義的MyPushButton)產生影響,而color:red表明所有的受影響控件的前景色都為red。
除了"類名","對象名","Qt屬性名"這三樣東西是大小寫敏感的外其他的東西都是大小寫不敏感的,如red 與Red代表同一屬性。

declaration部份是一系列的(屬性:值)對,使用分號(;)將各個不同的屬性值對分開,使用大括號({})將所有declaration包含在一起。

 

一般選擇器(selector)

Qt支持所有的CSS2定義的選擇器(鏈接類型除外),其祥細內容可以在w3c的網站上查找http://www.w3.org/TR/CSS2/selector.html , 其中比較常用的selector類型有:

通用類型選擇器:* 會對所有控件有效果。

類型選擇器:QPushButton匹配所有QPushButton的實例和其子類的實例。

屬性選擇器:QPushButton[flat="false"]匹配所有QPushButton屬性flat為false的實例,屬性分為兩種,靜態的和動態的,靜態屬性可以通過Q_PROPERTY() 來指定,來動態屬性可以使用setProperty來指定,如:
QLineEdit *nameEdit = new QLineEdit(this);
nameEdit->setProperty("mandatoryField", true);
如果在設置了qss后Qt屬性改變了,需要重新設置qss來使其生效,可以使用先unset再set qss

類選擇器:.QPushButton匹配所有QPushButton的實例,但不包含其子類,這相當於:*[class~="QPushButton"]     ~=的意思是測試一個QStringList類型的屬性是否包含給定的QString

ID選擇器:QPushButton#okButton對應Qt里面的object name設置,使用這條CSS之前要先設置對應控件的object name為okButton,如:Ok->setObjectName(tr("okButton"));

后裔選擇器:QDialog QPushButton匹配所有為QDialog后裔(包含兒子,與兒子的兒子的遞歸)為QPushButton的實例

子選擇器:QDialog > QPushButton匹配所有的QDialog直接子類QPushButton的實例,不包含兒子的兒子的遞歸。

偽選擇器:有兩種; 一種用於選擇Qt提供的Widgets類的子控件,一種用於選擇自定義狀態, 如QCheckBox:::checked 表示被勾選的復選框。 see   Qt Style Sheets Reference, 這里提供了Qt 所有的可以使用QSS 的 Widgets 及其分類, 以及其屬性列表。 

 

偽選擇器

  • 表示狀態的偽選擇器

以冒號(:)表示,與css里的偽選擇器相似,是基於控件的一些基本狀態來限定程序的規則,如hover規則表示鼠標經過控件時的狀態,而press表示按下按鈕時的狀態。如:

QPushButton:hover {

Background-color:red;

}

      表示鼠標經過時QPushButton背景變紅。

Pseudo還支持否定符號(!),如:                

QRadioButton:!hover { color: red }

表示沒有鼠標移上QRadioButton時他顯示的顏色是red。

Pseudo支持狀態的有效與、與非,有效或、或非比如:

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

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

     前者表示QPushButton在鼠標移上卻沒有點擊時顯示blue字,但如果點擊的時候就不會顯示blue顏色了。后者表示 checkbox 在被選中或者鼠標移動到其上時, 顏色變為白色

            同樣可以和以下所述的子控件選擇器一起聯合使用,如:

QSpinBox::down-button:hover { image: url(btn-combobox-press.bmp) }

與前面所講的一樣,偽選擇器,子控件選擇器等都是可以用逗號(,)分隔表示連續相同的設置的,如:
QPushButton:hover,QSpinBox::down-button, QCheckBox:checked { color: white ;image: url(btn-combobox-press.bmp);} 表示如下
更多請參考:http://pepper.troll.no/s60prereleases/doc/stylesheet-reference.html#list-of-pseudo-states

 

  • 表示子控件的偽選擇器

對於復雜的控件,可能會在其中包含其他子控件,如一個QComboxBox中有一個drop-down的按鈕。那么現在如果要設置QComboxBox的下拉按鈕的話,就可以這樣訪問:

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

     子控件選擇器是用位置的引用來代表一個元素,這個元素可以是一個單一控件或是另一個包含子控件的復合控件。使用subcontrol-origin屬性可以改變子控件的默認放置位置,如:

QComboBox {

margin-right: 20px;

}

QComboBox::drop-down {

subcontrol-origin: margin;

}

   如上語句可以用來改變drop-down的margin。

   相對位置屬性可以用來改變子控件相對於最初位置的偏移量,如當一個QCombox的drop-down按鈕被按下時,我們可以用一個內部的小偏移量來表示被按下的效果,如下:

QComboBox::down-arrow {

image: url(down_arrow.png);

}

QComboBox::down-arrow:pressed {

position: relative;

top: 1px; left: 1px;

}

   絕對位置屬性允許子控件改變自己的位置和大小而不受引用元素的控件。一但位置被設定了,這些子控件就可以被當成一般的widget來對待,並且可以使用合模型。關於合模型可以參考下面。

如果你要查看Qt支持哪些子控件選擇器,可以參考:http://pepper.troll.no/s60prereleases/doc/stylesheet-reference.html#list-of-sub-controls-syntax.html

解決沖突

使用specificity

在程序里面要先設置控件的,如:

btnOne = new QPushButton(centralWidget);

btnOne->setObjectName(QString::fromUtf8("btnOneCh"));

這樣,我們有了一個object name為btnOneCh的QPushButton,試驗一下,使用指定object name的方式,如:

QPushButton#btnOneCh { color: red }

QPushButton { color: white }

可以看出,btnOncCh的color變成了red。 

使用偽選擇器,如hover,press,enabled等,如:按扭"1"是disable了的,QPushButton:!enabled {color: white}

QSS 使用 specificity 來確定控件的樣式, 這一點跟 CSS 相同, 如上例中,前者的 specificity 大於后者 。 又如:

QPushButton:hover:enabled { color: white }

QPushButton:enabled { color: red }

            前者的 specificity 大於后者;

所有的類型選擇器都有一個共同的特性,就是如果有兩個屬性沖突了的話就會以最后出現的一個為准,如:

QPushButton:hover { color: white }

QPushButton:enabled { color: red }

            這個例子本來意思是pushbutton 正常時是紅色, 鼠標進入時是白色, 但是由於兩行代碼的specificity 相同,終的結果是第一行效果被覆蓋。 

        又如

QPushButton { color: red }

QAbstractButton { color: gray }

  人們會想當然以為 pushbutton的 顏色會是紅色, 因為pushbutton 是 abstractbutton的子類。 但是在Qt中, 所有類的 specificity 值是相同的, 所以最終的結果是 第一行效果被覆蓋。 

specificity 的計算方法參看 commment。 

 

Namespace沖突

類型選擇器能夠使用到一個特定的類型

如:

class MyPushButton : public QPushButton {

// ...

}

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

        因為QSS使用QObject::className來判斷要賦與style sheet的控件類型,如果一個用戶定義控件類型在一個namespace里面的話,QObject::className會返回<namespace>::<classname> 的名字,這和子控件選擇器的語法相沖突,為了解決此問題,使用"--"來代替"::"

比如:

namespace ns

{      

class MyPushButton : public QPushButton

{

          // ...      

}

}

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

 

如果有幾個selector指定了相同的declaration, 可以使用逗號(,)將各個選擇器分開,如:

QPushButton, QLineEdit, QComboBox { color: red }

他相當於:

QPushButton { color: red }

QLineEdit { color: red }

QComboBox { color: red }

 

級聯效應

級聯是指一個子類的 style 由自己的 qss 和 祖先(父類, 父類的父類……)合並而來, 但是如果子類里面設置了StyleSheet與父類里在設置的有沖突,那么子類無論是否符合specificity規則, 都會優先使用自己的。      

同樣,如果在qApp時面設置了,但是在某一個特定控件里面也設置,如果有沖突,也是優先使用控件自己的,例如,我在程序時面設置了:btnOneEn->setStyleSheet("QPushButton { color: red }");

而,當我再設置qApp時,如果,將QPushButton的color設置成grey的,那么結果是對於btnOneEn這個QPushButton來說他的顏色還是red。

這就是為什么這里設置為grey了btnOneEn卻還是red。 

如果我們對一個控件設置StyleSheet為:

QPushButton* myPushButton;

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

其實他和設置為:myPushButton->setStyleSheet("color: blue");
效果相同,只是后一種設置不會對QPushButton的子類產生作用,但第一種卻會。

css中,如果一個元素的font color 值沒有被顯式的定義,則它會繼承父節點的font color但是 QSS 中則不然。 

例如, 對於一個 包含了數個 pushbutton 的groupbox

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

 groupbox 的顏色為紅色, 但是pushbutton 的顏色還是系統顏色。除非如此設置

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

     Qt Widgets 的 pallete 和 font 是有級聯效應的, 也就是說, 一個控件設定了以后, 那么它的所有子控件都會被設定。 但是 Window 類型的除外。 除非設定了Qt::WA_WindowPropagation 參數。

    如果 QSS 的設定 和 Widgets 的屬性(目前只有font)沖突的話, 那么系統會采用QSS 的設定。  

設置對象屬性

如果在程序里面使用Q_PROPERTY設置的屬性,可以在qss里面使用:qproperty-<property name>的形式來訪問並設置值。

如:

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

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

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

如果屬性引用到的是一個由Q_ENUMS申明的enum 時,要引用其屬性名字要用定義的名稱而不是數字。

注意:對象屬性不支持 狀態偽選擇器

引用:http://pepper.troll.no/s60prereleases/doc/stylesheet

comments  

原文地址

         http://www.cnblogs.com/davesla/archive/2011/01/30/1947928.html

 

如何計算css選擇符的特異度

第一步,如果聲明代碼是在元素的style屬性里,也就是行內樣式(Inline Style)的話,那么該聲明代碼擁有最高的優先級,如果不是屬於行內樣式,那么跳到第二步;行內樣式例子:<span style="color:red:></span>;

第二步,統計ID選擇符的數量,數量越多的則特異度越高。如果擁有相同個數的ID選擇符,或者都沒有ID選擇符,那么跳到第三步;

第三步,統計類選擇符(如,.test),屬性選擇符(如,[type="submit"])和偽類(如,:hover)的總和,數值越大則特異度越高,如果總和相同或者都為0,那么跳到第四步;

第四步,統計元素類型選擇符(如,div)和偽元素(如,:first-letter),數值越大則特異度越高。

如果兩個或以上的選擇符擁有相同的物異度,那么根據css級聯的規則,后來者居上,也就是最后指定的將會被應用。

如果你想變得更加專業,那么可以參考W3C recommendation (6.4.3)的計算方法。計算結果用逗號分隔的a,b,c,d四列格式表示,其中a列的值是最重要的,而d的值則是最不重要的。一個選擇符的特異度計算方式如下:

1.計算a列的值,如果是行內樣式(Inline Style)的話,則該列的值為1,否則為0;

2.計算b列的值,值等於選擇符所有ID屬性個數的總和;

3.計算c列的值,值為選擇符非ID屬性的其他屬性個數及偽類個數的總和

4.計算d列的值,值為選擇符中的所有元素名個數及偽元素個數的總和

例如,一個形如"[id=p33]"的css屬性選擇符的計算結果如下是:a=0,b=0,c=1,d=0。

參照    http://www.laokboke.com/2011/10/07/how-to-calculate-specificity-of-css-selectors/

   

 

STYLE基礎知識的說明

我們控制STYLE主要是將STYLE添加到控件上,通過控制控件不同狀態的STYLE以達到整體的顯示效果

對於控件,我將其分解為以下幾部分來理解

Ø  從層次上來說:

控件可分為前景與背景

前景:多包含文件,圖片等內容

背景:多包含圖片,圖形等內容

   

Ø  從結構上來說:

由於QT style是模擬CSS的布局結構,因此其滿足CSS的盒子模型

   

從里到外的4個區域分別是:

1 content

2:  padding

3:  border

4:  margin

通過控制一個控件的前景,背景內容已經結構上的4個區域,我們就可以達到對一個控件為所欲為的控制

 CSS基本功能

CSS的強大在於組合功能的強大,這里只是簡單介紹基本功能,將簡單功能組合起來才能實現好看的效果。

CSS 背景屬性(Background)

屬性

描述

CSS

background

在一個聲明中設置所有的背景屬性。

1

background-attachment

設置背景圖像是否固定或者隨着頁面的其余部分滾動。

1

background-color

設置元素的背景顏色。

1

background-image

設置元素的背景圖像。

1

background-position

設置背景圖像的開始位置。

1

background-repeat

設置是否及如何重復背景圖像。

1

background-clip

規定背景的繪制區域。

3

background-origin

規定背景圖片的定位區域。

3

background-size

規定背景圖片的尺寸。

3

CSS 邊框屬性(Border 和 Outline)

屬性

描述

CSS

border

在一個聲明中設置所有的邊框屬性。

1

border-bottom

在一個聲明中設置所有的下邊框屬性。

1

border-bottom-color

設置下邊框的顏色。

2

border-bottom-style

設置下邊框的樣式。

2

border-bottom-width

設置下邊框的寬度。

1

border-color

設置四條邊框的顏色。

1

border-left

在一個聲明中設置所有的左邊框屬性。

1

border-left-color

設置左邊框的顏色。

2

border-left-style

設置左邊框的樣式。

2

border-left-width

設置左邊框的寬度。

1

border-right

在一個聲明中設置所有的右邊框屬性。

1

border-right-color

設置右邊框的顏色。

2

border-right-style

設置右邊框的樣式。

2

border-right-width

設置右邊框的寬度。

1

border-style

設置四條邊框的樣式。

1

border-top

在一個聲明中設置所有的上邊框屬性。

1

border-top-color

設置上邊框的顏色。

2

border-top-style

設置上邊框的樣式。

2

border-top-width

設置上邊框的寬度。

1

border-width

設置四條邊框的寬度。

1

outline

在一個聲明中設置所有的輪廓屬性。

2

outline-color

設置輪廓的顏色。

2

outline-style

設置輪廓的樣式。

2

outline-width

設置輪廓的寬度。

2

border-bottom-left-radius

定義邊框左下角的形狀。

3

border-bottom-right-radius

定義邊框右下角的形狀。

3

border-image

簡寫屬性,設置所有 border-image-* 屬性。

3

border-image-outset

規定邊框圖像區域超出邊框的量。

3

border-image-repeat

圖像邊框是否應平鋪(repeated)、鋪滿(rounded)或拉伸(stretched)

3

border-image-slice

規定圖像邊框的向內偏移。

3

border-image-source

規定用作邊框的圖片。

3

border-image-width

規定圖片邊框的寬度。

3

border-radius

簡寫屬性,設置所有四個 border-*-radius 屬性。

3

border-top-left-radius

定義邊框左上角的形狀。

3

border-top-right-radius

定義邊框右下角的形狀。

3

box-decoration-break

  

3

box-shadow

向方框添加一個或多個陰影。

3

Box 屬性

屬性

描述

CSS

overflow-x

如果內容溢出了元素內容區域,是否對內容的左/右邊緣進行裁剪。

3

overflow-y

如果內容溢出了元素內容區域,是否對內容的上/下邊緣進行裁剪。

3

overflow-style

規定溢出元素的首選滾動方法。

3

rotation

圍繞由 rotation-point 屬性定義的點對元素進行旋轉。

3

rotation-point

定義距離上左邊框邊緣的偏移點。

3

CSS 字體屬性(Font)

屬性

描述

CSS

font

在一個聲明中設置所有字體屬性。

1

font-family

規定文本的字體系列。

1

font-size

規定文本的字體尺寸。

1

font-size-adjust

為元素規定 aspect 值。

2

font-stretch

收縮或拉伸當前的字體系列。

2

font-style

規定文本的字體樣式。

1

font-variant

規定是否以小型大寫字母的字體顯示文本。

1

font-weight

規定字體的粗細。

1

CSS 外邊距屬性(Margin)

屬性

描述

CSS

margin

在一個聲明中設置所有外邊距屬性。

1

margin-bottom

設置元素的下外邊距。

1

margin-left

設置元素的左外邊距。

1

margin-right

設置元素的右外邊距。

1

margin-top

設置元素的上外邊距。

1

CSS 內邊距屬性(Padding)

屬性

描述

CSS

padding

在一個聲明中設置所有內邊距屬性。

1

padding-bottom

設置元素的下內邊距。

1

padding-left

設置元素的左內邊距。

1

padding-right

設置元素的右內邊距。

1

padding-top

設置元素的上內邊距。

1

CSS 定位屬性(Positioning)

屬性

描述

CSS

bottom

設置定位元素下外邊距邊界與其包含塊下邊界之間的偏移。

2

clear

規定元素的哪一側不允許其他浮動元素。

1

clip

剪裁絕對定位元素。

2

cursor

規定要顯示的光標的類型(形狀)。

2

display

規定元素應該生成的框的類型。

1

float

規定框是否應該浮動。

1

left

設置定位元素左外邊距邊界與其包含塊左邊界之間的偏移。

2

overflow

規定當內容溢出元素框時發生的事情。

2

position

規定元素的定位類型。

2

right

設置定位元素右外邊距邊界與其包含塊右邊界之間的偏移。

2

top

設置定位元素的上外邊距邊界與其包含塊上邊界之間的偏移。

2

vertical-align

設置元素的垂直對齊方式。

1

visibility

規定元素是否可見。

2

z-index

設置元素的堆疊順序。

  

  

  

  

  

  

  

  

  

CSS 文本屬性(Text)

屬性

描述

CSS

color

設置文本的顏色。

1

direction

規定文本的方向 / 書寫方向。

2

letter-spacing

設置字符間距。

1

line-height

設置行高。

1

text-align

規定文本的水平對齊方式。

1

text-decoration

規定添加到文本的裝飾效果。

1

text-indent

規定文本塊首行的縮進。

1

text-shadow

規定添加到文本的陰影效果。

2

text-transform

控制文本的大小寫。

1

unicode-bidi

設置文本方向。

2

white-space

規定如何處理元素中的空白。

1

word-spacing

設置單詞間距。

1

hanging-punctuation

規定標點字符是否位於線框之外。

3

punctuation-trim

規定是否對標點字符進行修剪。

3

text-align-last

設置如何對齊最后一行或緊挨着強制換行符之前的行。

3

text-emphasis

向元素的文本應用重點標記以及重點標記的前景色。

3

text-justify

規定當 text-align 設置為 "justify" 時所使用的對齊方法。

3

text-outline

規定文本的輪廓。

3

text-overflow

規定當文本溢出包含元素時發生的事情。

3

text-shadow

向文本添加陰影。

3

text-wrap

規定文本的換行規則。

3

word-break

規定非中日韓文本的換行規則。

3

word-wrap

允許對長的不可分割的單詞進行分割並換行到下一行。

3

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM