QT使用QSS進(jìn)行界面美化的完整步驟記錄
1. QSS
在網(wǎng)頁前端開發(fā)領(lǐng)域中,CSS 是?個?關(guān)重要的部分. 描述了?個網(wǎng)頁的 “樣式”,從而起到對網(wǎng)頁美化的作用.
所謂樣式, 包括不限于大小、位置、顏?、背景、間距、字體等等.
網(wǎng)頁開發(fā)作為 GUI 的典型代表,也對于其他客?端 GUI 開發(fā)產(chǎn)?了影響,Qt 也是其中之?.
1.1 基本語法
Qt 仿照 CSS 的模式,引?了 QSS,來對 Qt 中的控件做出樣式上的設(shè)定,從而允許程序猿寫出界?更好看的代碼
由于 Qt 本身的設(shè)計理念和網(wǎng)頁前端還是存在?定差異的,因此 QSS 中只能?持部分 CSS 屬性;整體來說 QSS 要比 CSS 更簡單?些
注意:如果通過 QSS 設(shè)置的樣式和通過 C++ 代碼設(shè)置的樣式?jīng)_突,則 QSS 優(yōu)先級更?
對于 CSS 來說, 基本的語法結(jié)構(gòu)?常簡單.
選擇器 {
屬性名: 屬性值;
}
QSS 沿?了這樣的設(shè)定.
選擇器 {
屬性名: 屬性值;
}
- 選擇器 描述了 “哪個 widget 要應(yīng)用樣式規(guī)則”
- 屬性 則是?個鍵值對,屬性名表?要設(shè)置哪種樣式,屬性值表?了設(shè)置的樣式的值.
QPushButton {
color: red;
}
上述代碼的含義表示,針對界?上所有的 QPushButton,都把文本顏色設(shè)置為紅色
1.2 設(shè)置方式
1.2.1 指定控件樣式設(shè)置
QWidget 中包含了 setStyleSheet 方法,可以直接設(shè)置樣式.
給指定控件設(shè)置樣式之后,該控件的子元素也會受到影響.
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 給 Widget 本?設(shè)置樣式.
//樣式對于子控件同樣生效
this->setStyleSheet("QPushButton { color: red;} ");
//ui->pushButton->setStyleSheet("QPushButton { color: red; }");
}
1.2.2 全局樣式設(shè)置
還可以通過 QApplication 的 setStyleSheet ?法設(shè)置整個程序的全局樣式.
全局樣式優(yōu)點(diǎn):
- 使同?個樣式針對多個控件?效,代碼更簡潔.
- 所有控件樣式內(nèi)聚在?起,便于維護(hù)和問題排查.

在 CSS 中也存在類似的優(yōu)先級規(guī)則,通常來說都是 “局部” 優(yōu)先級?于 “全局” 優(yōu)先級; 相當(dāng)于全局樣式先 “奠定基調(diào)” ,再通過指定控件樣式來 “特事特辦”
對于第?個按鈕來說,由于局部樣式的存在,它的顏色為綠色;對于第二個按鈕,兩種設(shè)置方式設(shè)置的樣式,疊加起來了,形如上述這種屬性疊加的效果,我們稱為 “層疊性”.
1.2.3 從文件加載樣式表
上述代碼都是把樣式通過硬編碼的方式設(shè)置的,這樣使 QSS 代碼和 C++ 代碼耦合在?起了,并不方便代碼的維護(hù),因此更好的做法是把樣式放到單獨(dú)的文件中,然后通過讀取文件的方式來加載樣式。
創(chuàng)建 style.qss 文件,并添加到 resource.qrc 中.
- style.qss 是需要程序運(yùn)?時加載的,為了規(guī)避絕對路徑的問題,仍然使用 qrc 的?式來組織 (即把資源?件內(nèi)容打包到 cpp 代碼中).
- Qt Creator 沒有提供創(chuàng)建 qss 文件的選項(xiàng),咱們直接 右鍵 -> 新建?件 -> ?動設(shè)置?件擴(kuò)展名為 qss 即可.

1.2.4 使用 Qt Designer 編輯樣式
QSS 也可以通過 Qt Designer 直接編輯,從而起到實(shí)時預(yù)覽的效果. 同時也能避免 C++ 和 QSS 代碼的耦合.
此時 Qt Designer 的預(yù)覽界?就會實(shí)時顯示出樣式的變化

當(dāng)我們發(fā)現(xiàn)?個控件的樣式不符合預(yù)期的時候, 要記得排查這四個地?:
- 全局樣式
- 指定控件樣式
- qss ?件中的樣式
- ui ?件中的樣式
2. 選擇器
QSS 的選擇器支持以下幾種:
| 選擇器 | 示例 | 說明 |
|---|---|---|
| 全局選擇器 | * | 選擇所有的 widget. |
| 類型選擇器 | QPushButton | 選擇所有的 QPushButton 和 其?類 的控件 |
| 類選擇器 | .QPushButton | 選擇所有的 QPushButton 的控件,不會選擇?類. |
| ID 選擇器 | #pushButton_2 | 選擇 objectName 為 pushButton_2 的控件 |
| 后代選擇器 | QDialog QPushButton | 選擇 QDialog 的所有后代(?控件, 孫?控件等等) 中的 QPushButton |
| ?選擇器 | QDialog > QPushButton | 選擇 QDialog 的所有?控件中的 QPushButton. |
| 并集選擇器 | QPushButton, QLineEdit, QComboBox | QPushButton, QLineEdit, QComboBox |
| 屬性選擇器 | QPushButton[flat=“false”] | 選擇所有 QPushButton 中,flat 屬性為 false 的控件. |
2.1 類型與類選擇器
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//類型選擇器,設(shè)置全局樣式
a.setStyleSheet("QWidget { color: red; }");
//類選擇器
//只是選擇 QWidget類, ?不會選擇QWidget 的?類 QPushButton了
a.setStyleSheet(".QWidget { color: green; }");
Widget w;
w.show();
return a.exec();
}
2.2 id選擇器
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 設(shè)置全局樣式
QString style = "";
//類型選擇器
style += "QPushButton { color: yellow; }";
//ID選擇器
style += "#pushButton { color: red; }";
style += "#pushButton_2 { color: green; }";
a.setStyleSheet(style);
Widget w;
w.show();
return a.exec();
}

當(dāng)某個控件身上,通過類型選擇器和 ID 選擇器設(shè)置了沖突的樣式時,ID 選擇器樣式優(yōu)先級更?.
同理,如果是其他的多種選擇器作?同?個控件時出現(xiàn)沖突的樣式,也會涉及到優(yōu)先級問題.
實(shí)踐中我們可以簡單的認(rèn)為,選擇器描述的范圍越精準(zhǔn),則優(yōu)先級越?,?般來說,ID 選擇器優(yōu)先級是最?的.
2.3 并集選擇器
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 設(shè)置全局樣式
a.setStyleSheet("QPushButton, QLabel, QLineEdit { color: red; } ");
Widget w;
w.show();
return a.exec();
}
運(yùn)行程序,可以看到這三種控件的文字顏?都設(shè)置為了紅色

并集選擇器是?種很好的代碼復(fù)用的?式,很多時候我們希望界?上的多個元素?格是統(tǒng)?的,就可以使?并集選擇器,把樣式屬性同時指定給多種控件
2.4 子控件選擇器
有些控件內(nèi)部包含了多個 “子控件” ,比如 QComboBox 的下拉后的?板,?如 QSpinBox 的上下按鈕等
可以通過子控件選擇器 :: ,針對上述?控件進(jìn)?樣式設(shè)置.

也可直接在Qt Designer中右側(cè)的屬性編輯器設(shè)置

2.5 偽類選擇器
偽類選擇器,是根據(jù)控件所處的某個狀態(tài)被選擇的,例如按鈕被按下,輸?框獲取到焦點(diǎn),?標(biāo)移動到某個控件上等.
- 當(dāng)狀態(tài)具備時,控件被選中,樣式?效.
- 當(dāng)狀態(tài)不具備時,控件不被選中,樣式失效.
使? : 的方式定義偽類選擇器
常用的偽類選擇器
| 偽類選擇器 | 說明 |
|---|---|
| :hover | ?標(biāo)放到控件上 |
| :pressed | ?標(biāo)左鍵按下時 |
| :focus | 獲取輸?焦點(diǎn)時 |
| :enabled | 元素處于可?狀態(tài)時 |
| :checked | 被勾選時 |
| :read-only | 元素為只讀狀態(tài)時 |
這些狀態(tài)可以使? ! 來取反. ?如 :!hover 就是?標(biāo)離開控件時, :!pressed 就是鼠標(biāo)松開時, 等等.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString style = "";
style += "QPushButton { color: red; }";
style += "QPushButton:hover { color: green; }";
style += "QPushButton:pressed { color: blue; }";
a.setStyleSheet(style);
Widget w;
w.show();
return a.exec();
}
可以看到,默認(rèn)情況下按鈕?字是紅?,?標(biāo)移動上去是綠?,?標(biāo)按下按鈕是藍(lán)?.

3. 樣式屬性
3.1 盒模型

?個遵守盒模型的控件,由上述幾個部分構(gòu)成
- Content 矩形區(qū)域:存放控件內(nèi)容,比如包含的文本/圖標(biāo)等.
- Border 矩形區(qū)域: 控件的邊框.
- Padding 矩形區(qū)域: 內(nèi)邊距,邊框和內(nèi)容之間的距離.
- Margin 矩形區(qū)域: 外邊距,邊框到控件 geometry 返回的矩形邊界的距離
默認(rèn)情況下,外邊距、內(nèi)邊距、邊框?qū)挾榷际?0
可以通過?些 QSS 屬性來設(shè)置上述的邊距和邊框的樣式
| QSS 屬性 | 說明 |
|---|---|
| margin | 設(shè)置四個?向的外邊距,復(fù)合屬性. |
| padding | 設(shè)置四個?向的內(nèi)邊距. 復(fù)合屬性. |
| border-style | 設(shè)置邊框樣式 |
| border-width | 邊框的粗細(xì) |
| border-color | 邊框的顏? |
| border | 復(fù)合屬性,相當(dāng)于 border-style + border-width + border-color |
下面,我們來設(shè)置一下邊框樣式與內(nèi)邊距

其中,border:5px solid red,相當(dāng)于 border-width: 5px; border-style: solid; border-color: red;(一般按照 寬度 → 樣式 → 顏色的順序書寫,其它方式可能會解析失?。?/p>
再來設(shè)置一下外邊距

其中,margin的可以寫多個,順序是:
上-> 右 -> 下-> 左
3.2 控件常用樣式
下?,我們給出?些常用控件的樣式示例
按鈕

復(fù)選框
使用藍(lán)色作為默認(rèn)形態(tài).
使用綠色作為 hover 形態(tài).
使用紅色作為 pressed 形態(tài).


單選框也是如此,這里就不演示了
| 要點(diǎn) | 說明 |
|---|---|
| ::indicator | ?控件選擇器. 選中 checkbox 中的對鉤部分 |
| width | 設(shè)置?控件寬度,對于普通控件?效 (普通控件使? geometry ?式設(shè)定尺?). |
| height | 設(shè)置?控件?度. 對于普通控件?效 |
| image | 設(shè)置?控件的圖?. |
輸入框
| 屬性 | 說明 |
|---|---|
| border-width | 設(shè)置邊框?qū)挾? |
| border-radius | 設(shè)置邊框圓? |
| border-color | 設(shè)置邊框顏? |
| border-style | 設(shè)置邊框?格. |
| color | 設(shè)置?字顏?. |
| background | 設(shè)置背景顏?. |
| selection-background-color | 設(shè)置選中?字的背景顏? |
| selection-color | 設(shè)置選中?字的?本顏?… |


關(guān)于顏色,其中有一個屬性
qlineargradientqlineargradient 有 6 個參數(shù):
- x1, y1: 標(biāo)注了?個起點(diǎn),
- x2, y2: 標(biāo)注了?個終點(diǎn),這兩個點(diǎn)描述了?個 “方向”,例如:
- x1: 0, y1: 0, x2: 0, y2: 1 就是垂直?向從上向下 進(jìn)?顏?漸變.
- x1: 0, y1: 0, x2: 1, y2: 0 就是?平?向從左向右 進(jìn)?顏?漸變.
- x1: 0, y1: 0, x2: 1, y2: 1 就是從左上往右下?向 進(jìn)?顏?漸變.
- stop0 和 stop1 描述了兩個顏?. 漸變過程就是從 stop0 往 stop1 進(jìn)?漸變的.

菜單欄
對于菜單欄而言,它可以分為菜單欄與菜單項(xiàng),它們各自有不同的樣式:
| 屬性 | 說明 |
|---|---|
| QMenuBar::item | 選中菜單欄中的元素 |
| QMenuBar::item:selected | 選中菜單來中的被選中的元素. |
| QMenuBar::item:pressed | 選中菜單欄中的?標(biāo)點(diǎn)擊的元素. |
| QMenu::item | 選中菜單中的元素 |
| QMenu::item:selected | 選中菜單中的被選中的元素. |
| QMenu::separator | 選中菜單中的分割線. |
下面,我們就做一個樣式稍微綜合一點(diǎn)的案例:登錄界面
首先,我們先使用Qt Designer拖拽出來幾個控件,然后使用布局布局管理器來設(shè)置一下

由于頂層窗?的 QWidget ?法設(shè)置背景圖?, 因此我們需要再套上?層 QFrame,背景圖?就可以設(shè)置到 QFrame 上即可
設(shè)置背景圖片,出來使用background-image之外,還有一個border-image,其中,border-image設(shè)置的背景,會隨著控件的大小而改變

QSS 本?給 Qt 提供了更豐富的樣式設(shè)置的能力,但是整體來說 QSS 的功能是不如 CSS 的,在 CSS 中,整個網(wǎng)頁的樣式,都是 CSS ?手負(fù)責(zé),CSS 功能更強(qiáng)大,并且也更可控。
相比之下,Qt 中是以原? api 為主,來控制控件之間的尺?、位置等,QSS 只是起到輔助的作?;?且 Qt 中提供的?些 “組合控件” (像 QComboBox, QSpinBox 等) 內(nèi)部的結(jié)構(gòu)是不透明的,此時進(jìn)??些樣式設(shè)置也會存在?定的局限性
4. 繪圖
雖然 Qt 已經(jīng)內(nèi)置了很多的控件,但是不能保證現(xiàn)有控件就可以應(yīng)對所有場景,很多時候我們需要更強(qiáng)的 “?定制” 能力。
Qt 提供了畫圖相關(guān)的 API,可以允許我們在窗?上繪制任意的圖形形狀,來完成更復(fù)雜的界?設(shè)計.
所謂的 “控件” ,本質(zhì)上也是通過畫圖的?式畫上去的,畫圖 API 和控件之間的關(guān)系,可以類?成機(jī)器指令和?級語?之間的關(guān)系。
控件是對畫圖 API 的進(jìn)?步封裝,畫圖 API 是控件的底層實(shí)現(xiàn).
繪圖 API 核?類
| 類 | 說明 |
|---|---|
| QPainter | ?來繪圖的對象,提供了?系列 drawXXX ?法,可以允許我們繪制各種圖形. |
| QPaintDevice | 描述了 QPainter 把圖形畫到哪個對象上。像咱們之前?過的 QWidget 也是?種 QPaintDevice (QWidget 是 QPaintDevice 的?類) . |
| QPen | 描述了 QPainter 畫出來的線是什么樣的 |
| QBrush | 描述了 QPainter 填充?個區(qū)域是什么樣的. |
繪圖 API 的使用,?般不會在 QWidget 的構(gòu)造函數(shù)中使用,而是要放到 paintEvent 事件中.
paintEvent 會在以下情況下被觸發(fā):
- 控件?次創(chuàng)建.
- 控件被遮擋,再解除遮擋.
- 窗口最小化,再恢復(fù).
- 窗口最小化,再恢復(fù).
- 控件大小發(fā)?變化時.
- 主動調(diào)? repaint() 或者 update() ?法(這兩個?法都是 QWidget 的?法).
4.1 繪制形狀
線段
//參數(shù): //p1:繪制起點(diǎn)坐標(biāo) //p2:繪制終點(diǎn)坐標(biāo) void drawLine(const QPoint &p1, const QPoint &p2);

矩形
//參數(shù): //x:窗?橫坐標(biāo); //y:窗?縱坐標(biāo); //width:所繪制矩形的寬度; //height:所繪制矩形的?度; void QPainter::drawRect(int x, int y, int width, int height);

圓
//參數(shù): //center:中?點(diǎn)坐標(biāo) //rx:橫坐標(biāo) //ry:縱坐標(biāo) void QPainter::drawEllipse(const QPoint ¢er, int rx, int ry)

4.2 繪制文本
文本
QPainter類 中不僅提供了繪制圖形的功能,還可以使用 QPainter::drawText() 函數(shù)來繪制?字,也可以使用QPainter::setFont() 設(shè)置字體等信息

畫筆
QPainter 在繪制時,是有?個默認(rèn)的畫筆的。在使?時也可以?定義畫筆,在 Qt 中,QPen類中定義了 QPainter 應(yīng)該如何繪制形狀、線條和輪廓。同時通過 QPen類 可以設(shè)置畫筆的線寬、顏?、樣式、畫刷等。
畫筆的顏?可以在實(shí)例化畫筆對象時進(jìn)?設(shè)置,畫筆的寬度是通過 setWidth() 方法進(jìn)?設(shè)置,畫筆的風(fēng)格是通過setStyle()方法進(jìn)行設(shè)置,設(shè)置畫刷主要是通過 setBrush() ?法。
- 設(shè)置畫筆顏?:QPen::QPen(const QColor &color)
- 設(shè)置畫筆寬度:void QPen::setWidth(int width)
- 設(shè)置畫筆風(fēng)格:void QPen::setStyle(Qt::PenStyle style)
其中,畫筆的風(fēng)格如下:


畫刷
畫刷是使用 QBrush類 來描述,畫刷大多用于填充。QBrush定義了QPainter的填充模式,具有樣式、顏?、漸變以及紋理等屬性。
畫刷的格式中定義了填充的樣式,使? Qt::BrushStyle 枚舉,默認(rèn)值是 Qt::NoBrush,也就是不進(jìn)?任何填充


4.3 繪制圖片
Qt 提供了四個類來處理圖像數(shù)據(jù):QImage、QPixmap、QBitmap 和 QPicture,它們都是常?的繪圖設(shè)備。
- QImage主要?來進(jìn)? I/O 處理,它對 I/O 處理操作進(jìn)?了優(yōu)化,?且可以?來直接訪問和操作像素;
- QPixmap 主要?來在屏幕上顯?圖像,它對在屏幕上顯?圖像進(jìn)?了優(yōu)化;
- QBitmap 是 QPixmap 的子類,用來處理顏?深度為1的圖像,即只能顯示黑白兩種顏?;
- QPicture ?來記錄并重演 QPainter 命令。
下面我們來簡單使用一下QPixmap:

平移圖片
平移圖片實(shí)際是通過改變坐標(biāo)來實(shí)現(xiàn)。QPainter類中提供了 translate()函數(shù) 來實(shí)現(xiàn)坐標(biāo)原點(diǎn)的改變

關(guān)于繪制圖片,還有很多很多的設(shè)置,我們這里就不贅述了。
- 旋轉(zhuǎn)圖?
- 移動畫家位置
- 保存/加載畫家的狀態(tài)
前?的代碼中我們是使? QWidget 作為繪圖設(shè)備,在 Qt 中還存在下列三個?較特殊的繪圖設(shè)備
- QPixmap
QPixmap 核心特性:
- 使? QPainter 直接在上?進(jìn)?繪制圖形.
- 通過?件路徑加載并顯?圖?.
- 搭配 QPainter 的 drawPixmap()函數(shù), 可以把這個圖?繪制到?個 QLabel、QPushButton 等控件上.
- 和系統(tǒng)/顯?設(shè)備強(qiáng)相關(guān), 不同系統(tǒng)/顯?設(shè)備下, QPixmap 的顯?可能會有所差別
- QImage
QImage 的核心特性:
- 使? QPainter 直接在上?進(jìn)?繪制圖形.
- 通過?件路徑保存/加載圖?.
- 能夠針對圖?進(jìn)?像素級別的操作(操作某個指定的像素).
- 獨(dú)?于硬件的繪制系統(tǒng), 能夠在不同系統(tǒng)之上提供?致的顯?.
- QPicture
QPicture 核?特性:
- 使? QPainter 直接在上?進(jìn)?繪制圖形.
- 通過?件路徑加載并顯?圖?.
- 能夠記錄 QPainter 的操作步驟.
- 獨(dú)?于硬件的繪制系統(tǒng), 能夠在不同系統(tǒng)之上提供?致的顯?.
總結(jié)
到此這篇關(guān)于QT使用QSS進(jìn)行界面美化的文章就介紹到這了,更多相關(guān)QT用QSS界面美化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言基礎(chǔ)知識點(diǎn)解析(extern,static,typedef,const)
本篇文章是對C語言基礎(chǔ)知識點(diǎn)(extern,static,typedef,const)的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下2013-10-10
C/C++詳解實(shí)現(xiàn)二層轉(zhuǎn)發(fā)
數(shù)據(jù)鏈路層是開放系統(tǒng)互連 (OSI) 模型中的第二層,該層用于通過 LAN 等單一網(wǎng)絡(luò)進(jìn)行通信的節(jié)點(diǎn),第二層數(shù)據(jù)包不能從一個網(wǎng)絡(luò)傳輸?shù)搅硪粋€網(wǎng)絡(luò)。而二層轉(zhuǎn)發(fā)是根據(jù)報文的目的MAC直接進(jìn)行轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)過程中不用對報文的頭部做任何的修改2022-05-05
利用C語言實(shí)現(xiàn)一個最簡單的飛機(jī)游戲
在前面彈跳小球?的基礎(chǔ)上實(shí)現(xiàn)一個簡單的飛機(jī)游戲,主要包括飛機(jī)的顯示、控制移動、顯示復(fù)雜圖案、發(fā)射激光、打靶練習(xí)等功能,感興趣的可以嘗試一下2022-10-10
Opencv實(shí)現(xiàn)用于圖像分割分水嶺算法
這篇文章主要為大家詳細(xì)介紹了Opencv實(shí)現(xiàn)用于圖像分割分水嶺算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01
C++11新特性“=default”,“=delete”的使用
=default、=delete 是C++11的新特性,分別為:顯式缺省(告知編譯器生成函數(shù)默認(rèn)的缺省版本)和顯式刪除(告知編譯器不生成函數(shù)默認(rèn)的缺省版本),本文就來介紹一下如何使用2021-05-05

