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

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

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

當我們發(fā)現(xiàn)?個控件的樣式不符合預期的時候, 要記得排查這四個地?:
- 全局樣式
- 指定控件樣式
- 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);
//類型選擇器,設置全局樣式
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);
// 設置全局樣式
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();
}

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

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

也可直接在Qt Designer中右側的屬性編輯器設置

2.5 偽類選擇器
偽類選擇器,是根據(jù)控件所處的某個狀態(tài)被選擇的,例如按鈕被按下,輸?框獲取到焦點,?標移動到某個控件上等.
- 當狀態(tài)具備時,控件被選中,樣式?效.
- 當狀態(tài)不具備時,控件不被選中,樣式失效.
使? : 的方式定義偽類選擇器
常用的偽類選擇器
| 偽類選擇器 | 說明 |
|---|---|
| :hover | ?標放到控件上 |
| :pressed | ?標左鍵按下時 |
| :focus | 獲取輸?焦點時 |
| :enabled | 元素處于可?狀態(tài)時 |
| :checked | 被勾選時 |
| :read-only | 元素為只讀狀態(tài)時 |
這些狀態(tài)可以使? ! 來取反. ?如 :!hover 就是?標離開控件時, :!pressed 就是鼠標松開時, 等等.
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();
}
可以看到,默認情況下按鈕?字是紅?,?標移動上去是綠?,?標按下按鈕是藍?.

3. 樣式屬性
3.1 盒模型

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

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

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

復選框
使用藍色作為默認形態(tài).
使用綠色作為 hover 形態(tài).
使用紅色作為 pressed 形態(tài).


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


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

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

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

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

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

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

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

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


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


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

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

關于繪制圖片,還有很多很多的設置,我們這里就不贅述了。
- 旋轉圖?
- 移動畫家位置
- 保存/加載畫家的狀態(tài)
前?的代碼中我們是使? QWidget 作為繪圖設備,在 Qt 中還存在下列三個?較特殊的繪圖設備
- QPixmap
QPixmap 核心特性:
- 使? QPainter 直接在上?進?繪制圖形.
- 通過?件路徑加載并顯?圖?.
- 搭配 QPainter 的 drawPixmap()函數(shù), 可以把這個圖?繪制到?個 QLabel、QPushButton 等控件上.
- 和系統(tǒng)/顯?設備強相關, 不同系統(tǒng)/顯?設備下, QPixmap 的顯?可能會有所差別
- QImage
QImage 的核心特性:
- 使? QPainter 直接在上?進?繪制圖形.
- 通過?件路徑保存/加載圖?.
- 能夠針對圖?進?像素級別的操作(操作某個指定的像素).
- 獨?于硬件的繪制系統(tǒng), 能夠在不同系統(tǒng)之上提供?致的顯?.
- QPicture
QPicture 核?特性:
- 使? QPainter 直接在上?進?繪制圖形.
- 通過?件路徑加載并顯?圖?.
- 能夠記錄 QPainter 的操作步驟.
- 獨?于硬件的繪制系統(tǒng), 能夠在不同系統(tǒng)之上提供?致的顯?.
總結
到此這篇關于QT使用QSS進行界面美化的文章就介紹到這了,更多相關QT用QSS界面美化內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C語言基礎知識點解析(extern,static,typedef,const)
本篇文章是對C語言基礎知識點(extern,static,typedef,const)的用法進行了詳細的分析介紹,需要的朋友可以過來參考下2013-10-10
C++11新特性“=default”,“=delete”的使用
=default、=delete 是C++11的新特性,分別為:顯式缺省(告知編譯器生成函數(shù)默認的缺省版本)和顯式刪除(告知編譯器不生成函數(shù)默認的缺省版本),本文就來介紹一下如何使用2021-05-05

