【QT】QT界面的美容院 -- QSS

发布于:2025-04-15 ⋅ 阅读:(21) ⋅ 点赞:(0)

一、背景介绍

🔥 在网页前端开发领域中,CSS 是一个至关重要的部分,描述了一个网页的 “样式”,从而起到对网页 美化 的作用。

网页开发作为 GUI 的典型代表,也对于其他客户端 GUI 开发产生了影响,Qt 也是其中之一。

  • Qt 仿照 CSS 的模式,引入了 QSS,来对 Qt 中的控件做出样式上的设定,从而允许我们写出界面更好看的代码。
  • 同样受到 HTML 的影响,Qt 还引入了 QML 来描述界面,甚至还可以直接把一个原生的 html 页面加载到界面上。
  • 当然,由于 Qt 本身的设计理念和网页前端还是存在一定差异的,因此 QSS 中只能支持部分 CSS 属性。整体来说 QSS 要比 CSS 更简单一些。

注意:如果通过 QSS 设置的样式和通过 C++ 代码设置的样式冲突,则 QSS 优先级更高。

二、基本语法

对于 CSS 来说,基本的语法结构非常简单。

QSS 沿用了其设定:

选择器 {
    属性名: 属性值; 
}

其中:

  • 选择器 描述了 “哪个 widget 要应用样式规则”
  • 属性则是一个 键值对 ,属性名表示要设置哪种样式,属性值表示了设置的样式的值。

例如:

QPushButton { color: red; }
//或者:
QPushButton {
    color: red;
}
  • 上述代码的含义表示,针对界面上所有的 QPushButton,都把文本颜色设置为红色

编写 QSS 时使用单行 和多行的格式均可。

【基本使用】

新建项目,以 Widget 作为基类,构造函数代码如下:

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QGridLayout* layout = new QGridLayout();

    QPushButton* button1 = new QPushButton("红色");
    QPushButton* button2 = new QPushButton("无色");

    button1->setStyleSheet("QPushButton{color:red;}");
    layout->addWidget(button1, 0, 0);
    layout->addWidget(button2, 0, 1);

    this->setLayout(layout);
}

结果如下:

image-20250201160501449

**注意:**上述代码中,只针对这一个按钮通过 setStyleSheet 方法设置的样式,此时这个样式仅针对该按钮生效。如果创建其他按钮,其他按钮不会受到影响。

三、基本语法

1. 指定控件样式设置

QWidget 中包含了 setStyleSheet 方法,可以直接设置样式。

  • 另一方面,给指定控件设置样式之后,该控件的子元素也会受到影响。

【子元素受到影响】

A. 在界面上创建两个按钮和一个单行编辑框

B. 修改 widget.cpp

这次不再给按钮设置样式,而是给 Widget 设置样式(Widget 是 QPushButton 的父控件)

image-20250201163646291

  • 可以看到 样式 对于 this 的子控件按钮同样会生效,但是必须是和选择器相关的

2. 全局样式设置

可以通过 QApplicationsetStyleSheet 方法设置整个程序的全局样式。

全局样式优点:

  • 使同一个样式针对多个控件生效,代码更简洁。
  • 把界面上所有控件样式内聚在⼀起,便于维护和问题排查。

image-20250201180411861

3. 样式的层叠特性

如果通过 全局样式 给某个控件设置了属性 1,通过 指定控件样式 给控件设置属性 2,那么这两个属性都会产生作用

比如:基于上面全局样式的设计,我们给 按钮1 设置字体大小,如下:

image-20250201180624931

可以看到,对于第一个按钮来说,同时具备了颜色和字体大小样式,而第二个按钮只有颜色样式。

说明针对第一个按钮,两种设置方式设置的样式叠加起来了。

  • 形如上述这种属性叠加的效果被称为 “层叠性”

CSS 全称为 Cascading Style Sheets,其中 Cascading 就是 “层叠性” 的意思,QSS 也继承了这样的设定。实际上把 QSS 叫做 QCSS 也许更合适一些。

注意:局部样式无法叠加,除非写到一行中,如下:

image-20250201181111911

4. 样式优先级

如果全局样式和指定控件样式冲突,则指定控件样式优先展示

  • 这里就不做演示了

在 CSS 中也存在类似的优先级规则。通常来说都是 “局部” 优先级高于 “全局” 优先级,相当于全局样式先 “奠定基调”,再通过指定控件样式来 “特事特办”。

  • 实际开发中,可以在全局样式中设置比较通用的样式来统一整个程序的界面风格。
  • 如果 需要针对某个控件进行微调,可以使用局部样式来做出调整

5. 从文件加载样式表

上述代码都是把样式通过硬编码的方式设置的,这样使 QSS 代码和 C++ 代码 耦合 在一起了,并不方便代码的维护。

因此更好的做法是把 样式放到单独的文件中,然后通过读取文件的方式来加载样式

操作如下:

A. 在界面上创建一个按钮

B. 创建 resource.qrc 文件(Qt -> Qt Resource File),并设定前缀为 /

img

C. 创建 style.qss 文件,并添加到 resource.qrc 中

  • style.qss 是需要程序运行时加载的,为了规避绝对路径的问题,仍然使用 qrc 的方式来组织(即把资源文件内容打包到 cpp 代码中)
  • Qt Creator 没有提供创建 qss 文件的选项,直接 “右键” -> “新建” -> “文本文档”,手动设置文件扩展名为 qss 即可

image-20250202112632742

使用 Qt Creator 打开 style.qss,编写内容

image-20250202112750370

新增一个函数来加载样式,如下:
image-20250202113026885

理论上来说 Qt 应该要提供直接从文件加载样式表的接口。

  • 类似于 setStyleSheetFromFile(const QString& path) 这种,在内部把读文件操作封好。

6. 使用 Qt Designer 编辑样式表

QSS 也可以通过 Qt Designer 直接编辑,从而起到 实时预览的效果

  • 同时也能避免 C++ 和 QSS 代码的 耦合

image-20250202113445075

如下:

image-20250202113543789

这种方式设置样式,样式内容会被以 xml 格式记录到 ui 文件中,如下:

img

同时在控件的 styleSheet 属性中也会体现:

img

💡 由于设置样式太灵活,有很多地方都能设置,所以当我们发现一个控件的样式不符合预期的时候,要记得排查这几个地方:

  • 全局样式(QAppplication 设置的)
  • 指定控件样式(这个控件是否设置了样式)
  • 指定控件的父控件的样式(可能是从父控件继承过来的)
  • qss 文件中的样式
  • ui 文件中的样式

在实际开发中,如果需要设置样式,建议最好 统一使用某一种方式 来设置。

四、选择器

1. 选择器概况

QSS 的****选择器****支持以下几种:

选择器类型 示例 说明
全局选择器 * 选择所有的 widget。
类型选择器 (type selector) QPushButton 选择所有的 QPushButton 和其子类的控件。
类选择器 (class selector) .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 的控件。
  • 总体来说,QSS 选择器的规则和 CSS 选择器基本一致。

【使用类型选择器选中子类控件】

① 在界面上创建一个按钮,修改 main.cpp,设置全局样式

a.setStyleSheet("QWidget{color:red;}");
  • 注意 :此处选择器使用的是 QWidget。QPushButton 也是 QWidget 的子类,所以会受到 QWidget 选择器的影响。

image-20250202134425319

  • 可以看到按钮的文本颜色已经是红色了

② 但是 💢如果把上述样式代码修改为下列代码

a.setStyleSheet(".QWidget{color:red;}");
【使用 id 选择器】

在开发中,如果期望不同的控件样式不同,此时就需要使用到 ID 选择器了

① 在界面上创建 3 个按钮,objectName 为 pushButton、pushButton_2、pushButton_3

② 编写 main.cpp,设置全局样式

  • 先通过 QPushButton 设置所有的按钮为红色。

  • 再通过 #pushButton#pushButton_2 分别设置这两个按钮为绿色和黄色。

image-20250202135015078

当某个控件身上,通过类型选择器和 ID 选择器 设置了冲突的样式 时,ID 选择器样式优先级更高(遵循局部优先)

同理,如果是其他的多种选择器作用同一个控件时出现冲突的样式,也会涉及到优先级问题。Qt 文档上有具体的优先级规则介绍(参见 The Style Sheet Syntax 的 Conflict Resolution 章节)

img

这里的规则计算起来非常复杂(CSS 中也存在类似的设定)。可以简单的认为,选择器描述的范围越精准,则优先级越高。一般来说,ID 选择器优先级是最高的。

如果属性不冲突,还是会同时生效

【使用并集选择器】

创建三个按钮、一个 label、一个单行输入框,编写 main.cpp,设置全局样式

QString style="QPushButton,QLineEdit,QLabel{color:red;}";
 
a.setStyleSheet(style);

此时就可以看到这三种控件的文字颜色都设置为了红色:

  • 并集选择器是一种很好的代码复用的方式,很多时候我们希望界面上的多个元素风格是统一的,就可以使用并集选择器,把样式属性同时指定给多种控件。

也可以指定 id 选择器:

QString style="#pushButton_2,QLineEdit,QLabel{color:red;}";

image-20250202140539465

2. 子控件选择器(Sub-Controls)

有些控件内部包含了多个 “子控件”,比如 QComboBox 的下拉后的面板,比如 QSpinBox 的上下按钮等。

可以通过 子控件选择器 :: ,针对上述子控件进行样式设置。

哪些控件拥有哪些子控件,参考文档 Qt Style Sheets Reference 中 List of Sub-Controls 章节
img

【设置下拉框的下拉按钮样式】

① 在界面上创建一个下拉框,并创建几个选项

image-20250202141045752

② 创建 resource.qrc,并导入图片 downPull.png

image-20250202141150914

img

③ 修改 main.cpp,编写全局样式

  • 使用子控件选择器 QComboBox::down-arrow 选中了 QComboBox 的下拉按钮。
  • 再通过 image 属性设置图片。
QString style="QComboBox::down-arrow{ image:url(:/downPull.png)}";
a.setStyleSheet(style);

结果如下:

image-20250202141519724

3. 伪类选择器(Pseudo-States)

伪类选择器,是根据 控件所处的某个状态 被选择的。

例如按钮被按下,输入框获取到焦点,鼠标移动到某个控件上等。

  • 当状态具备时,控件被选中,样式生效。
  • 当状态不具备时,控件不被选中,样式失效。

使用 : 的方式 定义伪类选择器

常用的伪类选择器:

伪类选择器 说明
:hover 鼠标放到控件上
:pressed 鼠标左键按下时
:focus 获取输入焦点时
:enabled 元素处于可用状态时
:checked 被勾选时
:read-only 元素为只读状态时

这些状态可以使用 ! 来取反,比如 :!hover 就是鼠标离开控件时,:!pressed 就是鼠标松开时,等等。更多伪类选择器的详细情况可以参考 Qt Style Sheets Reference 的 Pseudo-States 章节。

【设置按钮的伪类样式】

在界面上创建一个按钮,编写 main.cpp,创建 全局样式

QString style = "QPushButton { color: red; }";
style += "QPushButton:hover { color: green; }";
style += "QPushButton:pressed { color: blue; }";

a.setStyleSheet(style);

运行程序,结果如下:

img

  • 可以看到默认情况下按钮文字是红色,鼠标移动上去是绿色,鼠标按下按钮是蓝色

上述代码也可以使用事件的方式来实现。

【使用事件方式实现同样效果】

① 创建 MyPushButton 类,继承自 QPushButton

② 把生成代码中的构造函数 改成带参数 QWidget* 版本的构造函数(否则无法和 Qt Designer 生成的代码适配),如下:

// mypushbutton.h
#include <QPushButton>
 
class MyPushButton : public QPushButton
{
public:
    MyPushButton(QWidget* parent);
};
 
 
 
// mypushbutton.cpp
#include "mypushbutton.h"
MyPushButton::MyPushButton(QWidget* parent) : QPushButton(parent)
{
 
}

③ 在界面上创建按钮,并提升为 MyPushButton 类型

  • 右键按钮,选择 “提升为…”
  • 填写提升的类名和头文件:

img

提升完毕后,在右侧对象树这里,就可以看到类型的变化。

img

④ 重写 MyPushButton 的四个事件处理函数

a. 修改 mypushbutton.h

class MyPushButton : public QPushButton
{
public:
    MyPushButton(QWidget* parent);
 
    void mousePressEvent(QMouseEvent* e);
    void mouseReleaseEvent(QMouseEvent* e);
    void enterEvent(QEvent* e);
    void leaveEvent(QEvent* e);
};

b. 修改 mypushbutton.cpp

  • 初始化设为红色
  • 鼠标进入时设为绿色,离开是还原红色
  • 鼠标按下时设为蓝色,松开时还原绿色(松开时鼠标还是在按钮里)
MyPushButton::MyPushButton(QWidget* parent) : QPushButton(parent)
{
    this->setStyleSheet("QPushButton { color: red; }");
}
 
void MyPushButton::mousePressEvent(QMouseEvent *e)
{
    this->setStyleSheet("QPushButton { color: blue; }");
}
 
void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
{
    this->setStyleSheet("QPushButton { color: green; }");
}
 
void MyPushButton::enterEvent(QEvent *e)
{
    this->setStyleSheet("QPushButton { color: green; }");
}
 
void MyPushButton::leaveEvent(QEvent *e)
{
    this->setStyleSheet("QPushButton { color: red; }");
}
  • 运行程序可以看到效果和上述案例一致

很明显,实现同样的功能,伪类选择器要比事件的方式简单很多。

但是不能就说事件机制就不好,事件可以完成的功能很多,不仅仅是样式的改变,还可以包含其他业务逻辑,这一点是 伪类选择器 无法替代的。

五、样式属性

QSS 中的样式属性非常多,大部分的属性和 CSS 是非常相似的。

  • 文档的 Qt Style Sheets Reference 章节详细介绍了哪些控件可以设置属性,每个控件都能设置哪些属性等。

image-20250202143545891

1. 盒模型(Box Model)

  • 这个词 主要来自于 CSS

在文档的 Customizing Qt Widgets Using Style SheetsThe Box Model 章节介绍了盒模型

img

⼀个遵守盒模型的控件,由上述几个部分构成

  • Content 矩形区域:存放控件内容,比如包含的文本 / 图标等。
  • Border 矩形区域:控件的边框。
  • Padding 矩形区域:内边距,边框和内容之间的距离。
  • Margin 矩形区域:外边距,边框到控件 geometry 返回的矩形边界的距离。
  • 默认情况下,外边距、内边距、边框宽度都是 0。

可以通过一些 QSS 属性来设置上述的边距和边框的样式:

QSS 属性 说明
margin 设置四个方向的外边距。复合属性。
padding 设置四个方向的内边距。复合属性。
border-style 设置边框样式
border-width 边框的粗细
border-color 边框的颜色

这里的复合属性:由多个属性构成,margin 可以拆成如下:

  • margin-left
  • margin-right
  • margin-top
  • margin-bottom

当然实际运用的时候,写 margin: 10px; ==> 表示四个方向都是 10px 的外边距,而写 margin: 10px 20px; 则是上下都是 10px, 左右是 20px, margin: 10px 20px 30px 40px ==> 上右下左(顺时针)

  • 同样 padding 也可以拆成 4 个属性的

【设置边框和内边距】

在界面上创建一个 label,修改 main.cpp, 设置全局样式

QString style = "QLabel{border: 20px solid green; padding-left: 50px}";
a.setStyleSheet(style);
  • border: 20px solid green 相当于 border-style: solid; border-width: 2px; border-color: green; 三个属性的简写形式。
  • padding-left: 50px; 是给左侧设置内边距。

结果如下:

image-20250202144713960

【设置外边距】

为了方便确定控件位置,演示外边距效果,使用代码创建⼀个按钮。修改 widget.cpp,创建按钮,并设置样式

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton* button = new QPushButton(this);
    button->setGeometry(0, 0, 100, 100);
    button->setText("按钮");
    button->setStyleSheet("QPushButton{border: 5px solid red; margin: 20px}");

    qDebug() << button->geometry();
}

运行程序如下:

image-20250202151310020

可以看到,当前按钮的边框被外边距挤的缩小了,但是获取到的按钮的 Geometry 是不变的。

2. 控件样式示例(Box Model)

① 自定义按钮

A. 界面上创建一个按钮

B. 右键 -> 改变样式表,使用 Qt Designer 设置样式

img

C. 执行程序,点击 “按钮”:

img

属性 说明
font-size 设置文字大小。
border-radius 设置圆角矩形。 数值设置的越大,角就越圆。
background-color 设置背景颜色。
② 自定义复选框

A. 创建一个 resource.qrc 文件,并导入以下图片

image-20250202152808327image-20250202152837718image-20250202152850132image-20250202152857961image-20250202152904725image-20250202152912954

  • 使用黑色作为默认形态
  • 使用蓝色作为 hover 形态
  • 使用红色作为 pressed 形态

⚽ 使用阿里矢量图标库,可以下载到上述图片,下载的时候可以手动选择颜色

注意这里的文件命名。

image-20250202153026411

B. 创建一个复选框,并且用样式表来编辑复选框的样式

QCheckBox {
    font-size: 20px;
}
 
QCheckBox::indicator {
    width: 20px;
    height: 20px;
}
 
QCheckBox::indicator:unchecked {
    image: url(:/checkbox-unchecked.png);
}
 
QCheckBox::indicator:unchecked:hover {
    image: url(:/checkbox-unchecked_hover.png);
}
 
QCheckBox::indicator:unchecked:pressed {
    image: url(:/checkbox-unchecked_pressed.png);
}
 
QCheckBox::indicator:checked {
    image: url(:/checkbox-checked.png);
}
 
QCheckBox::indicator:checked:hover {
    image: url(:/checkbox-checked_hover.png);
}
 
QCheckBox::indicator:checked:pressed {
    image: url(:/checkbox-checked_pressed.png);
}
  • 鼠标点击选中,再取消的过程,可以看到此时的复选框就变得丰富起来了:

img

要点 说明
::indicator 子控件选择器。 选中 checkbox 中的对钩部分。
:hover 伪类选择器。 选中鼠标移动上去的状态。
:pressed 伪类选择器。 选中鼠标按下的状态。
:checked 伪类选择器。 选中 checkbox 被选中的状态。
:unchecked 伪类选择器。 选中 checkbox 未被选中的状态。
width 设置子控件宽度。 对于普通控件无效(普通控件使用 geometry 方式设定尺寸)。
height 设置子控件高度。 对于普通控件无效(普通控件使用 geometry 方式设定尺寸)。
image 设置子控件的图片。 像 QSpinBox, QComboBox 等可以使用这个属性来设置子控件的图片。
③ 自定义单选框

A. 创建 resource.qrc 文件,并导入以下图片

img

  • 使用黑色作为默认形态
  • 使用蓝色作为 hover 形态
  • 使用红色作为 pressed 形态

B. 在界面上创建两个单选按钮,并且在 Qt Designer 中编写样式

  • 此处为了让所有 QRadioButton 都能生效,把样式设置在 Widget 上了,并且使用后代选择器选中了 QWidget 里面的 QRadioButton。
 QWidget QRadioButton {
    font-size: 20px;
}
 
QWidget QRadioButton::indicator {
    width: 20px;
    height: 20px;
}
 
QWidget QRadioButton::indicator:unchecked {
    image: url(:/radio-unchecked.png);
}
 
QWidget QRadioButton::indicator:unchecked:hover {
    image: url(:/radio-unchecked_hover.png);
}
 
QWidget QRadioButton::indicator:unchecked:pressed {
    image: url(:/radio-unchecked_pressed.png);
}
 
QWidget QRadioButton::indicator:checked {
    image: url(:/radio-checked.png);
}
 
QWidget QRadioButton::indicator:checked:hover {
    image: url(:/radio-checked_hover.png);
}
 
QWidget QRadioButton::indicator:checked:pressed {
    image: url(:/radio-checked_pressed.png);
}

运行程序,如下:

img

注意 :

  • QSS 中有些属性,子元素能继承父元素(例如 font-size、color 等),但是也有很多属性是不能继承的。
  • 具体哪些能继承哪些不能继承,规则比较复杂,我们不去具体研究,实践中我们编写更精准的选择器是上策。
④ 自定义输入框

A. 在界面上创建一个单行编辑框,在 Qt Designer 中编写样式

QLineEdit {
 border-width: 2px; 
 border-radius: 20px;
 border-color: rgb(170, 170, 255);
 border-style: solid;
 padding: 0 8px;
 color: rgb(170, 85, 127);
 background:rgb(220, 220, 225);
 selection-background-color: rgb(0, 180, 0);
 selection-color: rgb(180, 0, 0);
}

B. 执行程序,输入文本,并且选中 :

image-20250202161340303

属性 说明
border-width 设置边框宽度。
border-radius 设置边框圆角。
border-color 设置边框颜色。
border-style 设置边框风格。
padding 设置内边距。
color 设置文字颜色。
background 设置背景颜色。
selection-background-color 设置选中文字的背景颜色。
selection-color 设置选中文字的文本颜色。
  • 这里 background 其实也可以用 background-color 的
⑤ 自定义列表

A. 在界面上创建一个 ListView,然后在样式表中编写代码,如下:

QListView::item:hover {
 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
 stop: 0 #FAFBFE, stop: 1 #DCDEF1);
}
QListView::item:selected {
 border: 1px solid #6a6ea9;
 background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
 stop: 0 #6a6ea9, stop: 1 #888dd9);
}

B. 然后将其变形成为 ListWidget,然后右击进行编辑项目,如下:

image-20250202155239152

C. 执行程序,结果如下:

image-20250202155328463

要点 说明
::item 选中 QListView 中的具体条目。
:hover 选中鼠标悬停的条目
:selected 选中某个被选中的条目。
background 设置背景颜色
border 设置边框。
qlineargradient 设置渐变色。

💡 对于渐变色理解

qlineargradient 有 6 个参数。

  • 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 进行渐变的。

举个例子:

现在新建一个项目,界面不创建任何任何控件,编写样式,如下:

QWidget {
    background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop: 0 #fff, stop: 1 #000);
}

修改代码》让其当前按照水平从左往右从白色过渡到黑色

QWidget {
    background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop: 0 #fff, stop: 1 #000);
}


⑥ 自定义菜单栏

A. 创建菜单栏,创建若干菜单项和一个分隔符:

B. 编写样式表,如下:

QMenuBar {
    background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 lightgray, stop:1 darkgray);
    spacing: 3px;
}
 
QMenuBar::item {
    padding: 1px 4px;
    background: transparent;
    border-radius: 4px;
}
 
QMenuBar::item:selected {
    background: #a8a8a8;
}
 
QMenuBar::item:pressed {
    background: #888888;
}
 
QMenu {
    background-color: white;
    margin: 0 2px;
}
 
QMenu::item {
    padding: 2px 25px 2px 20px;
    border: 3px solid transparent;
}
 
QMenu::item:selected {
    border-color: darkblue;
    background: rgba(100, 100, 100, 150);
}
 
QMenu::separator {
    height: 2px;
    background: lightblue;
    margin-left: 10px;
    margin-right: 5px;
}

执行代码,结果如下:

img

要点 说明
QMenuBar::item 选中菜单栏中的元素。
QMenuBar::item:selected 选中菜单栏中的被选中的元素。
QMenuBar::item:pressed 选中菜单栏中的鼠标点击的元素。
QMenu::item 选中菜单中的元素
QMenu::item:selected 选中菜单中的被选中的元素。
QMenu::separator 选中菜单中的分割线。

⑦ 登录界面
  • 【基于上述学习的 QSS 样式,来制作一个美化版本的登录界面】

A. 在界面上创建元素,并使用 布局管理器 把相关元素包裹一下

image-20250202162524988

  • 使用 QVBoxLayout 来管理上述控件。

  • 两个输入框和按钮的 minimumHeight 均设置为 30(元素在布局管理器中无法直接设置 width 和 height,使用 minimumWidthminimumHeight 代替,此时垂直方向的 sizePolicy 要设为 fixed)。

image-20250202162517629

  • 右键 QCheckBox,选择 Layout Alignment 可以设置 checkbox 的对齐方式(左对齐,居中对齐,右对齐)。

设置背景图片

创建 qrc 文件,导入背景图

image-20250202162949777

  • 第一想法:直接给 QWidget 顶层窗口设置背景图,但是 Qt 中存在限制 QWidget的顶层窗口 无法设置背景图片
  • 因此可以再套上一层 QFrame,背景图片就设置到 QFrame 上即可。

image-20250202163259469

编写 QFrame 的 QSS 样式:

QFrame{
   border-image:url(:/ship.jpg);
}
  • 使用 border-image 设置背景图片,而不是 background-image
  • 主要是因为 border-image 是可以自动缩放的,这一点在窗口大小发生改变时是非常有意义的。

效果如下:

image-20250202163538677

编写 CSS 代码(样式表):

  • 背景色使用 transparent 表示完全透明(应用父元素的背景)。
QFrame{
   border-image:url(:/ship.jpg);
}

QLineEdit {
    color: #8d98a1;
    background-color: #405361;
    padding: 0 5px;
    font-size: 20px;
    border-style: none;
    border-radius: 10px;
}
 
QCheckBox {
    color: white;
    background-color: transparent;
}
 
QPushButton {
    font-size: 20px;
    color: white;
    background-color: #5555;
    border-style: outset;
    border-radius: 10px;
}
 
QPushButton:pressed {
    color: black;
    background-color: #ced1db;
    border-style: inset;
}

然后还需要对两个输入框的 ui 做点改变,如下:

img

运行程序,最终效果如下:

image-20250202164239999

  • 最终完整样式代码,这些代码设置到 QFrame 的属性中即可。通常我们建议把样式代码集中放置,方便调整和排查。

六、小结

QSS 本身给 Qt 提供了更丰富的样式设置的能力,但是整体来说 QSS 的功能是不如 CSS 的。

  • 在 CSS 中,整个网页的样式都是 CSS 一手负责,CSS 功能更强大,并且也更可控。
  • 相比之下,Qt 中是以原生 API 为主,来控制控件之间的尺寸、位置等,QSS 只是起到辅助的作用。
  • 而且 Qt 中提供的一些 “组合控件”(像 QComboBox、QSpinBox 等)内部的结构是不透明的,此时进行一些样式设置也会存在一定的局限性。

另外,做出好看的界面,光靠 QSS 是不够的,更重要的是需要 专业美工做出设计稿

在这里插入图片描述