界面优化 - QSS

news2024/12/28 6:42:50

目录

1、背景介绍

2、基本语法

3、QSS 设置方式

3.1 指定控件样式设置

代码示例: 子元素受到影响

3.2 全局样式设置

代码示例: 使用全局样式

代码示例: 样式的层叠特性

代码示例: 样式的优先级

3.3 从文件加载样式表

代码示例: 从文件加载全局样式

3.4 使用 Qt Designer 编辑样式

代码示例: 使用 Qt Designer 编辑样式

4、选择器

4.1 选择器概况

代码示例: 使用类型选择器选中子类控件

代码示例: 使用 id 选择器

代码示例: 使用并集选择器

4.2 子控件选择器 (Sub-Controls)

代码示例: 设置下拉框的下拉按钮样式

4.3 伪类选择器 (Pseudo-States)

 代码示例: 设置按钮的伪类样式.


1、背景介绍

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

  • 所谓样式, 包括不限于大小, 位置, 颜色, 背景, 间距, 字体等等.

现在的网页很难找到没有 CSS 的. 可以说让 "界面好看" 是⼀个刚需.

一个程序的界面是否好看,是否重要呢?

  • 有些面向专业领域的程序,界面好看与否,不是很关键,更关键的是实际的效果。
  • 有些面向普通用户领域的程序,界面好看还是很大的加分项。

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

Qt 仿照 CSS 的模式, 引入了 QSS, 来对 Qt 中的控件做出样式上的设定, 从而允许程序猿写出界面更好看的代码.

  • 同样受到 HTML 的影响, Qt 还引入了 QML 来描述界面, 甚至还可以直接把一个原生的 html 页面加载到界面上.

注意:

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

2、基本语法

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

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

QSS 沿用了这样的设定.

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

其中:

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

例如:

QPushButton { color: red; }

 或者:

QPushButton {
    color: red;
}

上述代码的含义表示, 针对界面上所有的 QPushButton , 都把文本颜色设置为 红色 .

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

代码示例: QSS 基本使用

1) 在界面上创建⼀个按钮.

2) 编写代码, 设置样式

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

    ui->pushButton->setStyleSheet("QPushButton { color : red;}");
}

3) 运行程序, 观察效果. 可以看到文本已经是红色了.

注意:

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

3、QSS 设置方式

3.1 指定控件样式设置

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

上述代码我们已经演示了上述设置方式.


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

代码示例: 子元素受到影响

1) 在界面上创建一个按钮

2) 修改 widget.cpp, 这次我们不再给按钮设置样式, 而是给 Widget 设置样式 (Widget 是 QPushButton 的父控件).

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

    // 给 Widget 本身设置样式
    this->setStyleSheet("QPushButton { color : green;}");
}

3) 运行程序, 可以看到样式对于子控件按钮同样会生效.

3.2 全局样式设置

还可以通过 QApplication 的 setStyleSheet 方法设置整个程序的全局样式. 全局样式优点:

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

代码示例: 使用全局样式

1) 在界面上创建三个按钮.

2) 编辑 main.cpp, 设置全局样式

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置全局样式
    a.setStyleSheet("QPushButton{ color : red; }");

    Widget w;
    w.show();
    return a.exec();
}

3) 运行程序, 可以看到此时三个按钮的颜色都设置为红色了.


代码示例: 样式的层叠特性

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

1) 在界面上创建两个按钮

2) 编写 main.cpp, 设置全局样式, 把按钮文本设置为红色.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置全局样式
    a.setStyleSheet("QPushButton{ color : red; }");

    Widget w;
    w.show();
    return a.exec();
}

3) 编写 widget.cpp, 给第一个按钮设置字体大小.

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

    // 设定指定控件样式
    ui->pushButton->setStyleSheet("QPushButton{ font-size : 60px; }");
}

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

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

  1. 形如上述这种属性叠加的效果, 我们称为 "层叠性".

  2. CSS 全称为 Cascading Style Sheets, 其中 Cascading 就是 "层叠性" 的意思. QSS 也继承了这样的设定.
  3. 实际上把 QSS 叫做 QCSS 也许更合适⼀些~


代码示例: 样式的优先级

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

1) 在界面上创建两个按钮

2) 编辑 main.cpp, 把全局样式设置为红色.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置全局样式
    a.setStyleSheet("QPushButton{ color : red; }");

    Widget w;
    w.show();
    return a.exec();
}

3) 编辑 widget.cpp, 把第一个按钮样式设为绿色.

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

    // 设定指定控件样式
    ui->pushButton->setStyleSheet("QPushButton{ color : green; }");
}

4) 运行程序, 观察效果. 可以看到第一个按钮已经成为绿色了, 但是第二个按钮仍然是红色。

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

3.3 从文件加载样式表

  • 上述代码都是把样式通过硬编码的方式设置的. 这样使 QSS 代码和 C++ 代码耦合在一起了, 并不方便代码的维护.
  • 因此更好的做法是把样式放到单独的文件中, 然后通过读取文件的方式来加载样式.

代码示例: 从文件加载全局样式

1) 在界面上创建一个按钮

2) 创建 resource.qrc 文件, 并设定前缀为 / .

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

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

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

QPushButton {
    color : red;
}

5) 修改 main.cpp, 新增一个函数用来加载样式

QString loadQss(){
    QFile file(":/style.qss");
    // 打开文件
    file.open(QFile::ReadOnly);
    // 读取文件内容,虽然 readAll 返回的是 QByteArray, 但是 QString 提供了QByteArray 版本的构造函数
    QString style = file.readAll();
    // 关闭文件
    file.close();
    return style;
}

6) 修改 main.cpp, 在 main 函数中调用上述函数, 并设置样式.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 调用上述函数加载样式
    a.setStyleSheet(loadQss());

    Widget w;
    w.show();
    return a.exec();
}

7) 运行程序, 可以看到样式已经生效了.

3.4 使用 Qt Designer 编辑样式

        QSS 也可以通过 Qt Designer 直接编辑, 从而起到实时预览的效果. 同时也能避免 C++ 和 QSS 代码的耦合.

代码示例: 使用 Qt Designer 编辑样式

1) 在界面上创建⼀个按钮

2) 右键按钮, 选择 "改变样式表"

3) 在弹出的样式表编辑器中, 可以直接填写样式. 填写完毕, 点击 OK 即可.

4) 此时 Qt Designer 的预览界面就会实时显示出样式的变化.

5) 运行程序, 可以看到样式确实发生了改变.


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

<property name="styleSheet">
<string notr="true">QPushButton { color : blue; }</string>
</property>

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

当我们发现一个控件的样式不符合预期的时候, 要记得排查这四个地方:

  • 全局样式
  • 指定控件样式
  • qss 文件中的样式
  • ui 文件中的样式

4、选择器

4.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 的控件.

代码示例: 使用类型选择器选中子类控件

1) 在界面上创建一个按钮.

2) 修改 main.cpp, 设置全局样式

  • 注意, 此处选择器使用的是 QWidget . QPushButton 也是 QWidget 的子类, 所以会受到 QWidget 选择器的影响.
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置全局样式
    a.setStyleSheet("QWidget { color : red; }");

    Widget w;
    w.show();
    return a.exec();
}

 3) 运行程序, 可以看到按钮的文本颜色已经是红色了.

5) 如果把上述样式代码修改为下列代码

// 设置全局样式
a.setStyleSheet(".QWidget { color : red; }");

此时按钮的颜色不会发生改变. 此时只是选择 QWidget 类, 而不会选择 QWidget 的子类 QPushButton 了.


代码示例: 使用 id 选择器

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

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

  • 先通过 QPushButton 设置所有的按钮为黄色.
  • 再通过 #pushButton 和 #pushButton_2 分别设置这两个按钮为红色和绿色.
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置全局样式
    QString style = "";
    style += "QPushButton { color : yellow; }";
    style += "#pushButton_2 { color : red; }";
    style += "#pushButton_3 { color : green; }";
    a.setStyleSheet(style);

    Widget w;
    w.show();
    return a.exec();
}

 3) 执行程序, 观察效果

  • 当某个控件身上, 通过类型选择器和 ID 选择器设置了冲突的样式时, ID 选择器样式优先级更高.
  • 同理, 如果是其他的多种选择器作用同一个控件时出现冲突的样式, 也会涉及到优先级问题. Qt 文档上有具体的优先级规则介绍 (参见 The Style Sheet Syntax 的 Conflict Resolution 章节).
  • 实践中我们可以简单的认为, 选择器描述的范围越精准, 则优先级越高. 一般来说, ID 选择器优先级是最高的.

代码示例: 使用并集选择器

1) 创建按钮, label, 单行输入框

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

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 设置全局样式
    a.setStyleSheet("QPushButton, QLabel, QLineEdit { color : red; }");

    Widget w;
    w.show();
    return a.exec();
}

3) 运行程序, 可以看到这三种控件的文字颜色都设置为了红色

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

4.2 子控件选择器 (Sub-Controls)

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

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

🌴哪些控件拥有哪些子控件, 参考文档 Qt Style Sheets ReferenceList of Sub-Controls 章节.


代码示例: 设置下拉框的下拉按钮样式

1) 在界面上创建⼀个下拉框, 并创建几个选项

2) 创建 resource.qrc , 并导入图片 down.png

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

  • 使用子控件选择器 QComboBox::down-arrow 选中了 QComboBox 的下拉按钮.
  • 再通过 image 属性设置图片.
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString style = "";
    style += "QComboBox::down-arrow { image: url(:/down.png) }";
    a.setStyleSheet(style);

    Widget w;
    w.show();
    return a.exec();
}

 4) 执行程序, 观察效果

4.3 伪类选择器 (Pseudo-States)

伪类选择器, 是根据控件所处的某个状态被选择的. 例如按钮被按下, 输入框获取到焦点, 鼠标移动到某个控件上等.

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

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

常用的伪类选择器:

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

这些状态可以使用 ! 来取反. 比如 :!hover 就是鼠标离开控件时, :!pressed 就是鼠标松开时, 等等.

更多伪类选择器的详细情况, 参考 Qt Style Sheets ReferencePseudo-States 章节.


 代码示例: 设置按钮的伪类样式.

1) 在界面上创建⼀个按钮

2) 编写 main.cpp, 创建全局样式

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QString 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) 运行程序, 可以看到, 默认情况下按钮文字是红色, 鼠标移动上去是绿色, 鼠标按下按钮是蓝色.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2046125.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最新UI六零导航系统源码 | 多模版全开源

六零导航页 (LyLme Spage) 致力于简洁高效无广告的上网导航和搜索入口&#xff0c;支持后台添加链接、自定义搜索引擎&#xff0c;沉淀最具价值链接&#xff0c;全站无商业推广&#xff0c;简约而不简单。 使用PHPMySql&#xff0c;增加后台管理 多模板选择&#xff0c;支持在…

MySQL基础练习题46-每位经理的下属员工数量

目录 题目 准备数据 分析数据 总结 题目 我们将至少有一个其他员工需要向他汇报的员工&#xff0c;视为一个经理。 返回需要听取汇报的所有经理的 ID、名称、直接向该经理汇报的员工人数&#xff0c;以及这些员工的平均年龄&#xff0c;其中该平均年龄需要四舍五入到最接近…

【网络】IP分片与路径MTU发现

目录 MTU值 IP分片与重组 路径MTU发现 路径MTU发现原理 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 相关文章&#xff1a;【网络】从零认识IPv4-CSDN博客 MTU值 由于物理层的硬件限制&#xff0c;为了使网络性能最优&#xff0c;在数据链路层会有一个MTU值&#xff0…

算法【Java】—— 双指针算法

双指针算法 常见的双指针有对撞指针&#xff0c;快慢指针以及前后指针&#xff08;这个前后指针是指两个指针都是从从一个方向出发&#xff0c;去往另一个方法&#xff0c;也可以认为是小学学习过的两车并行&#xff0c;我也会叫做同向指针&#xff09;&#xff0c;在前后指针…

Python3网络爬虫开发实战(10)模拟登录(需补充账号池的构建)

文章目录 一、基于 Cookie 的模拟登录二、基于 JWT 模拟登入三、账号池四、基于 Cookie 模拟登录爬取实战五、基于JWT 的模拟登录爬取实战六、构建账号池 很多情况下&#xff0c;网站的一些数据需要登录才能查看&#xff0c;如果需要爬取这部分的数据&#xff0c;就需要实现模拟…

KNN图像识别实例--手写数字识别

目录 前言 一、导入库 二、导入图像并处理 1.导入图像 2.提取出图像中的数字 3.将列表转换成数组 4.获取特征数据集 5.获取标签数据 三、使用KNN模型 1.创建KNN模型并训练 2.KNN模型出厂前测试 3.使用测试集对KNN模型进行测试 四、传入单个图像&#xff0c;使用该模…

叉车高位盲区显示器 无线摄像头免打孔 视线遮挡的解决方案

叉车作业货叉叉货时&#xff0c;货叉升降无法看清位置&#xff0c;特别是仓储的堆高车&#xff0c;司机把头探出去才勉强可以靠经验找准方位&#xff01;一个不小心就可能叉歪了&#xff0c;使货物倾斜、跌落等等&#xff0c;从而发生事故&#xff01;如何将隐患扼杀&#xff0…

【JAVA入门】Day21 - 时间类

【JAVA入门】Day21 - 时间类 文章目录 【JAVA入门】Day21 - 时间类一、JDK7前的时间相关类1.1 Date1.2 SimpleDateFormat1.3 Calendar 二、JDK8新增的时间相关类2.1 Date 相关类2.1.1 ZoneId 时区2.1.2 Instant 时间戳2.1.3 ZoneDateTime 带时区的时间 2.2 DateTimeFormat 相关…

刷题DAY7

三个数的排序 题目&#xff1a;输入三个整数x&#xff0c;y&#xff0c;z&#xff0c;请把这三个数由小到大输出 输入&#xff1a;输入数据包含3个整数x&#xff0c;y&#xff0c;z&#xff0c;分别用逗号隔开 输出&#xff1a;输出由小到大排序后的结果&#xff0c;用空格隔…

O2OA开发知识-后端代理/接口脚本编写也能像前端一样用上debugger

在o2oa开发平台中&#xff0c;后端代理或者接口的脚本编写也能像前端一样用上debugger&#xff0c;这是来自藕粉社区用户的宝贵技术支持。 感谢藕粉社区论坛用户提供的技术分享&#xff01;tzengsh_BTstthttps://www.o2oa.net/forum/space-uid-4410.html 论坛地址&#xff1a…

【Kubernetes】k8s集群图形化管理工具之rancher

目录 一.Rancher概述 1.Rancher简介 2.Rancher与k8s的关系及区别 3.Rancher具有的优势 二.Rancher的安装部署 1.实验准备 2.安装 rancher 3.rancher的浏览器使用 一.Rancher概述 1.Rancher简介 Rancher 是一个开源的企业级多集群 Kubernetes 管理平台&#xff0c;实…

2024年高教社杯数学建模国赛A题思路解析+代码+论文

2024年高教社杯全国大学生数学建模竞赛&#xff08;以下简称国赛&#xff09;将于9月5日晚6时正式开始。 下文包含&#xff1a;2024国赛思路解析​、国赛参赛时间及规则信息说明、好用的数模技巧及如何备战数学建模竞赛 C君将会第一时间发布选题建议、所有题目的思路解析、相…

Axure:引领智慧时代的数据可视化原型设计先锋

在数字化转型的浪潮中&#xff0c;智慧农业、智慧城市、智慧社区、智慧水务等概念如雨后春笋般涌现&#xff0c;它们不仅重塑了我们的生活空间&#xff0c;也对数据可视化提出了前所未有的要求。作为原型设计领域的佼佼者&#xff0c;Axure RP凭借其强大的交互设计能力和直观的…

关于Nachi机器人自动运行上电条件

Nachi 机器人有两种控制柜&#xff0c;分别为 FD 控制柜和 CFD 控制柜。 对于 FD 控制器&#xff0c;执行以下操作。 1.旋转控制柜钥匙&#xff0c;使其对准标注位置①。 2.旋转示教器旋钮至下图所示位置。然后依次单击绿色按钮与白色按钮&#xff0c;机器人上电运行。 对于…

2025大数据毕业设计/计算机毕业设计创新必过选题(建议收藏)

一、大数据题目 项目架构模式&#xff1a; 1、数据Python爬虫&#xff1a;selenium、requests、DrissionPage等爬虫框架 2、hadoop、Spark、Flink&#xff08;PyFlink&#xff09;数据分析【可vmvare虚拟机可windwos电脑】 3、springboot、vue.js前后分离构建系统主体 4、…

排序篇——递归实现快速排序(hoare版-挖坑法-前后指针版)

目录 前言 一、key&#xff1f; 二、思路及代码实现 1.hoare版 2.挖坑法 3.前后指针版本 总结 前言 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。它会选出一个基准值(key)&#xff0c;把它放到正确的位置(排序之后的位置)。 提示&#xff1a;以下是本篇…

c语言学习,tolower ()函数分析

1&#xff1a;tolower() 函数说明&#xff1a; 检查参数c&#xff0c;为大写字母返回对应的小写字母 2&#xff1a;函数原型&#xff1a; int toascii(int c) 3&#xff1a;函数参数&#xff1a; 参数c&#xff0c;为检测整数 4&#xff1a;返回值&#xff1a; 返回转换的小…

【Python】生成二维迷宫的算法

前言 哈里最近因为一个小插曲打算写一个设计迷宫的算法。为了锻炼脑力&#xff0c;特地没有上网搜索而是自己摸索出一个迷宫设计算法。 概述 1、需求 哈里准备实现下图的迷宫。 2、分析 可以看到&#xff0c;图里凡是x和y坐标为单数时&#xff0c;总是白色。于是哈里得到下…

二分查找专题(总)

1、经典二分查找模板 int search(vector<int>& nums, int target) {int right nums.size() - 1;int left 0;while(left < right){int mid (left right)/2;if(nums[mid] > target){right mid-1;}else if(nums[mid] < target){left mid1;}else {return…

c语言-经典例题

C语言-经典例题 一、单项选择题 1、 -- A 2、 -- C y<5 --是关系运算符的优先级大于&& -- 是逻辑运算符 3、 -- B - D选项&#xff1a;c是float类型&#xff0c;所以c/2是1.5 4、 -- C 从后往前执行&#xff08;先算后面的&a…