目录

Qt界面优化

Qt:界面优化


Qt 中对于界面优化,采用的是 QSS,QSS 其实是参考的网页前端的 CSS,从名称就能看出来

QSS 能够针对界面的"样式"来进行设置

包括不限于: 大小, 位置, 颜色, 背景, 间距, 字体.….

CSS 的功能是非常强大,非常丰富的

QSS 要逊色一些,但也能完成很多的工作

有时候, 可以通过 QSS 设置样式 (设置字体属性)

也可以通过 C++ 代码设置样式

如果两者冲突,QSS 优先级更高


QSS的使用

语法结构:

选择器{
    属性名: 属性值;
    ......
}
  • 选择器: 先选择某个/某一类控件, 接下来进行的各种属性设置,都是针对选中的控件生效的
  • 键值对: 针对某些样式具体的设置了

例如:

QPushButton { 
    color: red; 
}

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


下面图形化界面的方式创建一个按钮:

https://i-blog.csdnimg.cn/direct/06c3d30dcff44d64b6b9f7a0e381a161.png

构造函数中修改颜色:

https://i-blog.csdnimg.cn/direct/61eaba7179804637aa9fc24b44654329.png

运行程序,按钮就变为红色了:

https://i-blog.csdnimg.cn/direct/3cf83b2425c64fa3a7b083d78624f223.png

如果有两个按钮,此时也只会对第一个按钮生效, 因为程序中针对的是 ui->pushButton,而没有针对 pushButton_2

设置样式的时候,是可以指定某个控件来设置的

指定控件之后,此时的样式就会针对这个指定的控件,也会针对子控件生效

如果我们代码改为 this,也就是整个 Widget:

https://i-blog.csdnimg.cn/direct/3b49ad96043e4666a180f77f396f126f.png

此时也会对 Widget 下面的子控件生效,也就是所有  QPushButton 都会生效:

https://i-blog.csdnimg.cn/direct/d4097bcb1aee40fe8824c93a4b3c294d.png


设置全局样式

也就是将界面上所有的样式都集中到一起来组织

全局样式的设置是需要在 main.cpp 中编写的,核心是通过 QApplication 的对象来进行设置

https://i-blog.csdnimg.cn/direct/3e29688959dc482e8a511edc90cc07b7.png

此时我们创建的三个按钮就全部是红色了:

https://i-blog.csdnimg.cn/direct/5b99f60235f7403ab78194321700bb4f.png

1.如果设置了全局样式,然后在某个控件里又设置了其他的样式,会咋样?

上面已经给全局样式设置了颜色为红色,全局样式并没有设置字体大小相关属性,这里我们给第一个按钮设置字体大小:

https://i-blog.csdnimg.cn/direct/e7eb80401edb4d12b3c08b05c4324319.png

效果如下:

https://i-blog.csdnimg.cn/direct/16036bc978f343f0a8f44654f6f7a679.png

从上面的样例可以看出,此时这两方面的样式,会"叠加"起来,叫做 层叠性

2.如果设置了全局样式,在某个控件里设置的样式和全局样式冲突了,又会咋样?

下面局部设置按钮2的颜色为绿色:

https://i-blog.csdnimg.cn/direct/2f5bc80901c443f585c68071e1ce8786.png

效果为:

https://i-blog.csdnimg.cn/direct/5bfba67581934eccaaa4cdbd68e2bc04.png

所以得到结论:

当全局样式和局部样式冲突的时候,局部样式的优先级是更高的,覆盖了对应的全局样式

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

样式和代码分离

QSS 上述代码中,样式代码和 C++ 代码都是混在一起的

  • 如果 QSS 样式代码比较简单,那是没什么问题的
  • 如果 QSS 代码非常复杂,继续这样搞,代码的维护成本就很高了

所以我们就可以把样式代码拎出来,放到单独的文件中,后续可以直接让 C++ 代码来读取并加载文件内容

首先创建一个按钮:

https://i-blog.csdnimg.cn/direct/66d6f6b22081463793d1f317f8467be2.png

下面进行三个步骤:

1.创建 qrc 文件, 通过 qrc 管理样式文件

2.创建单独的 qss 文件,把这样的文件放到 qrc 中

3.编写 C++ 代码, 读取 qss 文件中的内容,并设置样式

在对应文件夹中右键创建 style.qss

https://i-blog.csdnimg.cn/direct/1d0b56264ce44f4f93aca6303daf326e.png

选择 style.qss,此时就通过 qrc 管理样式文件了:

https://i-blog.csdnimg.cn/direct/81df82b6c59942b4b78e40c5ad4e9114.png

接着点击文件-打开,打开刚刚创建的 .qss 文件,添加下面内容:

https://i-blog.csdnimg.cn/direct/221ab4a6a0f64c06b31da22f681e535d.png

接着在 main.cpp 中,新创建一个函数去读取 qss 文件中的内容:

https://i-blog.csdnimg.cn/direct/ecb38e40749a4d61aa07f461c9d4c44b.png

此时按钮就按照 qss 文件内容改变样式了:

https://i-blog.csdnimg.cn/direct/05e63c5925e44a88b089f9ce92db2752.png

这个方案仅供大家参考,实际开发中还有更方便的方案


Qt Designer 中直接集成这样的功能,允许我们把样式直接写到 .ui 文件里

同样先创建一个按钮:

https://i-blog.csdnimg.cn/direct/66d6f6b22081463793d1f317f8467be2.png

选中整个页面,右键,点击 改变样式表:

https://i-blog.csdnimg.cn/direct/3d916ff1b522480989d3768381fd73d5.png

通过这里就可以编写界面的样式了,这里进行的修改都会记录到 ui 文件中,并且在程序运行时自动生效,而且这里还能进行预览

https://i-blog.csdnimg.cn/direct/274daa64401e434387f20074af3a2a6b.png

此时点击确定,就直接能预览修改后的效果:

https://i-blog.csdnimg.cn/direct/2dfe16262e5f4c5f8da2ed49f845027f.png

由于设置样式太灵活,有很多地方都能设置,就导致当某个控件样式不符合预期的时候,排查起来就比较麻烦了

所以排查时需要注意的地方很多:

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

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


选择器的用法

QSS 的选择器支持下面几种,其中加粗的是用的比较多的:

https://i-blog.csdnimg.cn/direct/d958a6b3fa2a455e945ae2eebbf03386.png


类型选择器

先创建一个按钮:

https://i-blog.csdnimg.cn/direct/66d6f6b22081463793d1f317f8467be2.png

在 main.cpp 中编写下面的代码:

https://i-blog.csdnimg.cn/direct/dfbd6a828cbd419c929a136e883db01f.png

此时按钮就会变为红色

上述的代码,前面的 QPushButton 其实就是 类型选择器 了(QWidget 也会变红,因为对子控件也会产生影响)


类选择器

但是如果使用 类选择器 ,也就是前面加上点,此时就不会对子类生效了:

https://i-blog.csdnimg.cn/direct/844add12f7264bb7a27c147d6a7a1790.png

效果为:

https://i-blog.csdnimg.cn/direct/66d6f6b22081463793d1f317f8467be2.png


id选择器

在开发中,期望不同的按钮控件样式不同,此时就需要使用 id选择器

在 main.cpp 中添加下面的代码,前面加 # 表示 id选择器:

https://i-blog.csdnimg.cn/direct/26a42f5372594ad7a5c50d5526cf2e13.png

此时运行程序,效果为:

https://i-blog.csdnimg.cn/direct/b06d7372ca804ddc906ce9a346ef0f2f.png

上述代码中,通过类型选择器其实也把第二、三个按钮选中了,但是后面又通过 id选择器 选中了,所以我们认为:

此时当类型选择器和 id 选择器选中同一个控件的时候,并且设置的样式是冲突的,此时 id 选择器的优先级更高

如果不冲突,那就会同时生效


并集选择器

并集选择器 可以同时选中多个控件

下面在添加一个 Label 和一个 line edit:

https://i-blog.csdnimg.cn/direct/3fa9a90716af4f56b460b82559a37eef.png

再在 main.cpp 中添加样式表:

https://i-blog.csdnimg.cn/direct/bbda1002f054486caf3262843e208b56.png

此时运行程序:

https://i-blog.csdnimg.cn/direct/c564d5700ef84f41ade85ee5cf5e4961.png

注意:上述使用并集选择器时,不光可以选择类型,也可以写成id:

https://i-blog.csdnimg.cn/direct/be404bd571fd4504a7f74e325f4a9537.png


子控件选择器

有些控件是比较复杂的,所以控件里面也会包含其他的控件

例如:

前面学习的 QSpinBox,后面还会有两个微调按钮,点击就会发送改变,像这种控件,我们就认为整个 QSpinBox 是一个总的控件,里面的两个按钮就是子控件

还有 QComboBox,整个 QComboBox 就是一个总控件,下拉框和下拉按钮就是子控件

如果想要了解 Qt 中哪些控件是有子控件的,就需要去查阅文档了:

直接搜索 Qt Style Sheets Reference

点击最下面的 List of Sub-Controls:

https://i-blog.csdnimg.cn/direct/f583713b90cb41ddae17dfa3d22cc393.png

点击后,就能看出来每一个子控件是从属于哪些控件的:

https://i-blog.csdnimg.cn/direct/b2d36c0120db4f67b2bc84fb675b1881.png


下面我们给 QComboBox 的下拉按钮添加一个图标,这时就需要采用子控件选择器了

初始下拉框样式如下:

https://i-blog.csdnimg.cn/direct/edf0e3ecf7f345a5993dba543746f42f.png

同样是通过 qrc机制 管理图片:

https://i-blog.csdnimg.cn/direct/3d05379aa1f04a758cbe61a2148869a2.png

在 main.cpp 中新增代码:

https://i-blog.csdnimg.cn/direct/1c379dab69a74c7fb04b0146c2ab2a2c.png

效果为:

https://i-blog.csdnimg.cn/direct/c0cd15ccd4194f89904e04c575ff673b.png


伪类选择器

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

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

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

常用的伪类选择器:

https://i-blog.csdnimg.cn/direct/8d774cd3aa65429abf257d511f55a1de.png

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

同样也可以在文档中查看,最后一个是子选择器,倒数第二个就是伪类选择器

https://i-blog.csdnimg.cn/direct/ff134db0205b4687b11aa7425b827a49.png

下面在 main.cpp 中演示 伪类选择器 的用法:

https://i-blog.csdnimg.cn/direct/e7ed4390b89d412cb40a7d1cd111d989.png

此时就能够做到,按钮为红色,鼠标放在按钮上变为绿色,鼠标按下按钮,变为蓝色

当然了,上述的功能,也可以通过事件的方式来实现,自己创建一个类继承自 QPushButton,再重写几个事件即可


盒子模型

box model:叫做盒子模型,也是来自于 CSS

https://i-blog.csdnimg.cn/direct/c50cbe0ada174f77a05e89e01e3f3e6a.png

  • margin:外边距
  • border:边框
  • padding:内边距
  • content:内容

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

https://i-blog.csdnimg.cn/direct/c02fe80c7bff433e996e9fb7f7c8ccb2.png

复合属性,指的是可以拆成4个属性,以 margin 为例,可以拆分为:

margin-left、margin-right、margin-top、​​​​​​​margin-bottom

在使用时(CSS也是这样设定的):

margin:10px;四个方向都是 10px 的外边距

margin: 10px 20px;上下是 10px,左右是 20px.

margin: 10px 20px 30px 40px;上右下左分别设定(顺时针)


下面演示具体的使用

首先创建一个 Label:

https://i-blog.csdnimg.cn/direct/90ddc8da2d104d4081a0920c368fe430.png

在 main.cpp 中设置全局样式:

https://i-blog.csdnimg.cn/direct/160d4808bb2242a589041effb2849022.png

效果为(padding改变的是文字和边框的距离):

https://i-blog.csdnimg.cn/direct/ea0ed199c2d84a03b38a0dfe0e6835e7.png


下面演示改变外边框:

先不设置外边距:

https://i-blog.csdnimg.cn/direct/9c5b7ff04445488a96aa3d87b04e3132.png

效果为:

https://i-blog.csdnimg.cn/direct/87cad5bc0a334690af62b9bf9d0b0d7f.png

设置外边距:

https://i-blog.csdnimg.cn/direct/dc85981c47c04183b20621701d691580.png

此时效果为(margin改变的是边框距离整个窗口左上角的距离):

https://i-blog.csdnimg.cn/direct/269d24cc036f4ab9b3d1c00cafc2cf4c.png

可以看到,再给按钮设置完外边距后,按钮大小缩小了,如果打印此时按钮的大小:

https://i-blog.csdnimg.cn/direct/c4a7c0e2b3b84898a77fa6940363a72a.png

发现尺寸还是 100*100:

https://i-blog.csdnimg.cn/direct/7e62794f02d14949a94d21abc6c47c2a.png

所以在指定外边距后,会让我们看起来的效果变小了,但是实际上占据的空间还是这么大


给按钮设置样式

首先创建一个按钮:

https://i-blog.csdnimg.cn/direct/66d6f6b22081463793d1f317f8467be2.png

右键按钮,编辑样式表:

https://i-blog.csdnimg.cn/direct/9013ed107421466c9ebd566e894c67f8.png

效果为:

https://i-blog.csdnimg.cn/direct/efcbc8b818e847619b5bb5a960423777.png

  • font-size 设置字体大小
  • border-radius 设置圆角矩形
  • background-color 设置背景色
  • color 设置文字颜色

给复选框设置样式

接下来给复选框设置样式,我们提前下载好三种方框,以及三种方框勾选后的图片,如下所示:

https://i-blog.csdnimg.cn/direct/82cfdf97fd3b46c7a67dede826915c2f.png

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

首先创建 checkBox 复选框:

https://i-blog.csdnimg.cn/direct/2b562ce83dbc49c894632abdab991755.png

接着使用 qrc机制 导入这几张图片:

https://i-blog.csdnimg.cn/direct/0737cd6ddd4c44fe8cb138014744b5d6.png

下面右键复选框,改变样式表,先将文字和框的大小变大些:

https://i-blog.csdnimg.cn/direct/f708fc376c3547d0923815a7f53bf5a7.png

效果为:

https://i-blog.csdnimg.cn/direct/29ea7914255a4f359462f750d9f6464b.png

下面需要使用子控件选择器,选择 checkBox 前面的 小框:

https://i-blog.csdnimg.cn/direct/03afb094ff744aad8df4cd61e95cdaa6.png

填写在 url 后面的括号时,可以点击上面的添加资源,比较方便:

https://i-blog.csdnimg.cn/direct/50ef30f004754b308a6ca5a8331c66d0.png

下面改变为:

https://i-blog.csdnimg.cn/direct/fd2e6c9afc274a009cfeaf17d7c658f6.png

默认是黑框,鼠标放上去是蓝框,点下去是红框

总结一下:

https://i-blog.csdnimg.cn/direct/eee02a74540f4f40a9647a144444a25a.png


给输入框设置样式

首先创建一个 line edit:

https://i-blog.csdnimg.cn/direct/5d742267895b430b84518df0ac879a5b.png

右键输入框,点击改变样式表:

https://i-blog.csdnimg.cn/direct/ffd12f5cf3b94da28afa1ee67f3cefd1.png

此时效果为:

https://i-blog.csdnimg.cn/direct/4be075cf4769422795a240e5bcee4e96.png

下面是一些属性说明:

https://i-blog.csdnimg.cn/direct/19b6e97ffc904ba0bb100bbbf3519c4e.png


给列表框设置样式

先创建一个 List Widget,并添加几个选项:

https://i-blog.csdnimg.cn/direct/d3809a71e482487e834e67066ba5ae4e.png

右键改变样式表:

https://i-blog.csdnimg.cn/direct/30663a79ac1d4812aea28acae3ddb0a5.png

效果为:

https://i-blog.csdnimg.cn/direct/4bf8b27b6f5343c08e6a8f02be4ea2cc.png

上述设置的是纯色的, 还可以设置渐变色,使用属性 qlineargradient 设置渐变色(线性渐变),此处需要填写六个参数:

坐标是非0即1的,也就是最小是0,最大是1

  • x1: 起点的横坐标
  • y1: 起点的纵坐标
  • x2: 终点的横坐标
  • y2: 终点的纵坐标
  • stop: 0 起始颜色
  • stop: 1 结束颜色

例如:

x1:0,y1: 0,x2: 1,y2: 0,就是从左到右的渐变

x1:0,y1: 0,x2: 0,y2: 1,就是从上到下的渐变

x1:0,y1: 0,x2: 1,y2: 1,就是从左上到右下的渐变,对角线方向

下面就改变样式表,改为渐变色:

https://i-blog.csdnimg.cn/direct/f4377b3d7f2847b6897a8982d3a3aedc.png

效果为:

https://i-blog.csdnimg.cn/direct/19a884c58283499eb7af285da998fa4d.png


给菜单栏设置样式

首先创建一个菜单,下面有几个菜单项:

https://i-blog.csdnimg.cn/direct/35048d32b7994358878823d0455dc916.png

针对整个窗口右键,改变样式表:

https://i-blog.csdnimg.cn/direct/43dab5ea68804d09b4609162450edcd5.png

  • spacing:菜单之间的间隔
  • QMenu::item 是为了选中某个菜单项时,字体不会变动(因为选择某个菜单项时会加上边框,与不加边框的字显示不桶了)

效果为:

https://i-blog.csdnimg.cn/direct/e0ab62ea0d86476cbe645566a5676ef8.png

一些要点:

https://i-blog.csdnimg.cn/direct/32c2250bf22a478ba2b42aa3a0ef838f.png


实现登录界面

在我们的日常生活中,登录界面可以说是随处可见了,下面就使用 Qt 实现一个登录界面,并使用 QSS 对它进行样式的设置

图形化界面的方式创建:

https://i-blog.csdnimg.cn/direct/45d692a718dc410394ab709d2badb8ce.png

因为将这几个控件放入布局管理器中了,所以不能设置大小了,但是我们可以通过设置最小高度、最大高度,来达到我们想要的高度

https://i-blog.csdnimg.cn/direct/f466b57733d94c418e2152fc9e7a6b59.png

接着我们想将这个登录界面设置的好看些,所以可以设置一下登录界面的背景图片,使用 qrc 导入图片

https://i-blog.csdnimg.cn/direct/5163a011a6864dd6aca021133ca3da61.png

直观想法,是直接给 QWidget 顶层窗口设置背景图

但是 Qt 中存在限制,直接给顶层窗口设置背景会失效

所以解决方式就是:

可以给上述控件外头套上一个和窗口一样大小的 QFrame 控件

https://i-blog.csdnimg.cn/direct/04b8af5b9da946949a836f3123907803.png

此时的关系如下所示,先是 QWidget,QWidget 里面有一个 QFrame,QFrame 里面才是这几个控件

https://i-blog.csdnimg.cn/direct/45e48224c24b4cab91cea4349075256a.png

下面鼠标点击上图的 QWidget,右键点击改变样式表:

https://i-blog.csdnimg.cn/direct/cf9699d176da45748c35294d6cead7da.png

Qt 中设置背景图,除了 background-image 之外,还有 border-image 属性

  • background-image:背景图片固定大小
  • border-image:通过这种方式设置的背景,会自动跟随控件的大小变化(推荐)

效果为:

https://i-blog.csdnimg.cn/direct/08bb467e9a9547eb993da71c0569a7db.png

接着继续设置其他样式:

https://i-blog.csdnimg.cn/direct/fd149440ef0c4a1abd19818e1062ccc2.png

此时效果如下:

https://i-blog.csdnimg.cn/direct/eb3a5d9a22554914b379e400dce73092.png


Qt:界面优化到此结束