ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Qt — 界面优化

Qt — 界面优化 目录1. QSS1.1 背景介绍1.2 基本语法1.3 设置全局样式1.4 样式和代码分离方案1方案21.5 选择器1.5.1 选择器的概况1.6 子控件选择器1.6.1 给 QComboBox 下拉按钮设置图片1.6.2 修改进度条的颜色1.7 伪类选择器1.8 样式属性1.8.1 盒模型Box Model1.9 控件样式1.9.1 按钮1.9.2 复选框1.9.3 输入框1.9.4 列表框1.9.5 菜单栏1.9.6 登陆界面2. 绘图2.1 基本概念2.2 绘制各种形状2.2.1 绘制线段2.2.2 绘制矩形2.2.3 绘制圆形2.2.4 绘制文本2.2.5 设置画笔2.2.6 设置画刷2.3 绘制图片2.3.1 图片的缩放2.3.2 图片的旋转1. QSS1.1 背景介绍QSS - 网页前端 CSS能够针对界面的 “样式” 来进行设置 样式包括不限于大小位置颜色背景间距字体……CSS 的功能是非常强大的非常丰富的QSS 要逊色一些但是也能完成很多的工作。有时候可以通过 QSS 设置样式设置字体属性也可以通过 C 代码设置样式如果二者冲突QSS 的优先级更高。1.2 基本语法对于 CSS 来说, 基本的语法结构⾮常简单.选择器 {属性名: 属性值;}QSS 沿⽤了这样的设定.选择器 {属性名: 属性值;}选择器先选择某个/某一类控件接下里进行的各种属性设置都是针对选中的控件生效的。键值对针对某些样式具体的设置了egQPushButton { color: red; }或者QPushButton {color: red;}上述代码的含义表示, 针对界⾯上所有的 QPushButton , 都把文本颜色设置为 红色 。运行设置样式的时候是可以指定某个控件 来设置的。指定控件之后此时的样式就会针对这个指定的控件也会针对子控件生效。但是由于 QPushButton 没有子控件了。会针对 this 的子控件也会生效。既是要考虑到子控件也是要和选择器相关的。运行添加一个 Line Edit 的话就不行可以看见文本颜色是黑色。1.3 设置全局样式界面上所有的样式都集中到一起来组织。运行1. 如果设置了全局样式然后再某个控件里又设置了其它的样式会怎样——此时这两方面的样式会叠加起来运行QSS 从 CSS 这里参考过来的因此 QSS 中也继承了层叠性2. 如果设置了全局样式在某个控件里设置的样式和全局样式冲突了又会怎样——当全局样式和局部样式冲突的时候局部样式的优先级是更高的覆盖了对应的全局样式。运行1.4 样式和代码分离方案1实际开放中就可以在全局样式中设置比较通用的样式统一整个程序的界面风格。如果需要针对某个控件进行微调可以使用局部样式来做调整。QSS 上述代码中样式代码和C代码都是混在一起的。如果 QSS 样式比较简单无所谓了但是如果 QSS 代码比较复杂继续这样写的话维护的成本就很高了。此时就可以把样式代码拎出来放到单独的文件中。后续可以直接让 C 代码来读取并加载文件内容。创建 qrc 文件通过 qrc 管理样式文件创建单独的 qss 文件把这样的文件放到 qrc 中编写 C 代码读取 qss 文件中的内容并设置样式右键添加文件重命名编写 style.qss 文件运行上述的方案仅供参考实际开发中还有更方便的方案。方案2Qt Designer 中直接集成这样的功能允许我们把样式直接写到 .ui 文件中。通过这里的就可以编写界面的样式了这里进行的修改都会记录到 ui 文件中并且在程序运行时自动生效并且这里还能进行预览记录了当前编辑的样式后续 Qt 根据 ui 文件 生成 C 代码也就回同时把样式设置进去。由于设置样式太灵活有很多地方都能设置就导致当某个控件样式不符合预期的时候排查起来比较麻烦全局样式QApplication 设置的指定控件的样式这个控件是否设置了样式指定控件的父控件的样式可能是从父控件继承过来的qss 文件中的样式ui 文件中的样式……实际开发中如果需要设置样式建议最好统一使用某一种方式来设置。1.5 选择器1.5.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[flatfalse]选择所有 QPushButton 中, flat 属性为 false 的控件.总体来说, QSS 选择器的规则和 CSS 选择器基本⼀致.上述选择器也不需要全都掌握, 就只熟悉最常⽤的⼏个即可(上述加粗的).QPushButton 就是类型选择器将 QPushButton 改为 QWidget由于 QPushButton 是 QWidget 的子类所以也能生效此时就是类选择器只针对 Widget 生效不会选中子类在开发中期望不同的控件样式不同此时就需要使用 id 选择器了就能选择一个了因为 id 是唯一的。# 后面跟的就是 objectname。运行此时类型选择器和 id 选择器选中同一个控件的时候并且设置的样式是冲突的此时id 选择器的优先级更高。如果不冲突两种样式都会同时生效。运行并集选择器运行在并集选择器中不一定是类型选择器也可以是 id 选择器运行1.6 子控件选择器有些控件内部包含了多个 ⼦控件 . 比如 QComboBox 的下拉后的⾯板, 比如 QSpinBox 的上下按钮等.可以通过⼦控件选择器 :: , 针对上述⼦控件进⾏样式设置.QSpinBoxQComboBox手册中里面便有很多的子控件1.6.1 给 QComboBox 下拉按钮设置图片加载图标运行1.6.2 修改进度条的颜色QProgressBar::chunk {background-color: #FF0000;}1.7 伪类选择器伪类选择器, 是根据控件所处的某个状态被选择的. 例如按钮被按下, 输⼊框获取到焦点, ⿏标移动到某个控件上等当状态具备时, 控件被选中, 样式⽣效.当状态不具备时, 控件不被选中, 样式失效.使⽤ : 的⽅式定义伪类选择器.常⽤的伪类选择器伪类选择器说明:hover⿏标放到控件上:pressed⿏标左键按下时:focus获取输⼊焦点时:enabled元素处于可⽤状态时:checked被勾选时:read-only元素为只读状态时这些状态可以使⽤ ! 来取反. 比如 :!hover 就是⿏标离开控件时, :!pressed 就是⿏标松开时,等等.运行上述也可通过事件的方式来实现但是有点麻烦。1.8 样式属性QSS 中的样式属性⾮常多, 不需要都记住. 核⼼原则还是⽤到了就去查.⼤部分的属性和 CSS 是⾮常相似的.文档中搜索Qt Style Sheets Reference在翻阅⽂档的时候涉及到⼀个关键术语 盒模型 (Box Model).1.8.1 盒模型Box Model⼀个遵守盒模型的控件, 由上述⼏个部分构成.Content 矩形区域: 存放控件内容. ⽐如包含的⽂本/图标等.Border 矩形区域: 控件的边框.Padding 矩形区域: 内边距. 边框和内容之间的距离.Margin 矩形区域: 外边距. 边框到控件 geometry 返回的矩形边界的距离默认情况下, 外边距, 内边距, 边框宽度都是 0可以通过⼀些 QSS 属性来设置上述的边距和边框的样式.QSS 属性说明margin设置四个⽅向的外边距. 复合属性.padding设置四个⽅向的外边距. 复合属性.border-style设置边框样式border-width边框的粗细border-color边框的颜⾊border复合属性, 相当于 border-style border-width border-color复合属性margin 、padding、可以拆分成4个属性margin-leftmargin-rightmargin-topmargin-bottommargin: 10px; 四个方向都是10px的外边距margin: 10px 20px; 上下是10px左右是20px的外边距margin: 10px 20px 30px 40px; 上右下左顺时针方向内边距外边距运行运行1.9 控件样式下⾯给出⼀些常⽤控件的样式⽰例.1.9.1 按钮右键 - 改变样式表, 使⽤ Qt Designer 设置样式QPushButton {font-size:22px;border:4px dashed rgb(32, 3, 255);border-radius:15px;background-color:rgb(174, 218, 255);color:rgb(255, 85, 0)}QPushButton:pressed {background-color:rgb(217, 179, 255)}运行属性说明font-size设置⽂字⼤⼩.border-radius设置圆⻆矩形.数值设置的越⼤, ⻆就 越圆.background-color设置背景颜⾊1.9.2 复选框创建⼀个 resource.qrc ⽂件, 并导⼊以下图片使⽤蓝色作为默认形态.使⽤绿色作为 hover 形态.使⽤红色作为 pressed 形态.对复选框整体的样式QCheckBox {font-size:20px;}QCheckBox::indicator {width:20px;height:20px;}样式表QCheckBox {font-size:20px;}QCheckBox::indicator {width:20px;height:20px;}QCheckBox::indicator:unchecked{image:url(:/Uncheckedblue.png);}QCheckBox::indicator:unchecked:hover{image:url(:/Uncheckedgreen.png);}QCheckBox::indicator:unchecked:pressed{image:url(:/Uncheckedred.png);}QCheckBox::indicator:checked{image:url(:/checkedblue.png);}QCheckBox::indicator:checked:hover{image:url(:/checkedred.png);}QCheckBox::indicator:checked:pressed{image:url(:/checkedgreen.png);}运行要点说明::indicator⼦控件选择器.选中 checkbox 中的对钩部分:hover伪类选择器.选中⿏标移动上去的状态.:pressed伪类选择器.选中⿏标按下的状态.:checked伪类选择器.选中 checkbox 被选中的状态.:unchecked伪类选择器.选中 checkbox 未被选中的状态.width设置⼦控件宽度.对于普通控件⽆效 (普通控件使⽤ geometry ⽅式设定尺⼨).height设置⼦控件⾼度.对于普通控件⽆效 (普通控件使⽤ geometry ⽅式设定尺⼨).image设置⼦控件的图片像 QSpinBox, QComboBox 等可以使⽤这个属性来设置⼦控件的图片1.9.3 输入框在界⾯上创建⼀个单行编辑框修改样式表QLineEdit {border-width:2px;border-color:rgb(111, 98, 255);border-style:solid;border-radius:20px;font-size:22px;padding-left:10px;color:rgb(2, 118, 50);background-color:rgb(255, 247, 133);selection-color:rgb(255, 39, 96);selection-background-color:rgb(255, 200, 33);}运行属性说明border-width设置边框宽度.border-radius设置边框圆⻆.border-color设置边框颜⾊.border-style设置边框⻛格.padding设置内边距.color设置⽂字颜⾊.background设置背景颜⾊.selection-background-color设置选中⽂字的背景颜⾊.selection-color设置选中⽂字的⽂本颜⾊1.9.4 列表框在界⾯上创建⼀个 ListWidget修改上面鼠标选中和放上去的效果QListWidget:item:hover{background-color:rgb(211, 255, 190);}QListWidget:item:selected{background-color:rgb(59, 148, 44);}运行上面设置的是纯色选中的区域各个位置的颜色都是一样的。但是 Qt 还支持渐变色左侧设置一种颜色右侧设置一种颜色从左往右达到颜色的渐变。qlineargradient 设置渐变色线性渐变此处要填写6个参数x1起点的横坐标这里的取值是非常有限的要么是0要么是1y1起点的纵坐标这里的取值是非常有限的要么是0要么是1x2终点的横坐标这里的取值是非常有限的要么是0要么是1y2终点的纵坐标这里的取值是非常有限的要么是0要么是1stop: 0 起始颜色stop: 1 结束颜色QListWidget:item:hover{background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(211, 255, 190), stop:1 rgb(249, 249, 249));}QListWidget:item:selected{background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(59, 148, 44), stop:1 rgb(249, 249, 249));}运行1.9.5 菜单栏原始界面QMenuBar {background-color:rgb(255, 152, 219);spacing:5px;}QMenuBar::item {border-radius:5px;padding:3px 10px;background-color:rgb(209, 201, 255);}QMenuBar::item:selected {background-color:rgb(205, 255, 202);}QMenu:item {border:2px dashed transparent; // transparent 透明的padiing:2px 10px;}QMenu::item:selected {border:2px solid rgb(255, 121, 12);background-color:rgb(255, 253, 193);}QMenu::separator {height:2px;background-color:rgb(85, 170, 127);margin:0 5px;}运行要点说明QMenuBar::item选中菜单栏中的元素.QMenuBar::item:selected选中菜单来中的被选中的元素.QMenuBar::item:pressed选中菜单栏中的⿏标点击的元素.QMenu::item选中菜单中的元素QMenu::item:selected选中菜单中的被选中的元素.QMenu::separator选中菜单中的分割线.1.9.6 登陆界面让一个窗口变得更好看最明显的就是设置背景图片最直接的想法是给 QWidget 顶层窗口设置背景图但是 Qt 中存在限制直接给顶层窗口设置背景会失效。--- 在已有的控件外面套上一个和窗口一样大小的 QFrame 控件。QFrame 控件是 QWidget 的一个子类导入图片让 Frame 铺满整个窗口改变样式在Widget 和 frame 中均可但是推荐在 frame 中更好Qt 中设置背景图除了 background-image 之外还有 border-image 属性更推荐 border-image 因为通过这种方式设置的背景会自动跟随控件的大小变化。而 background-image 是固定大小。QFrame {border-image:url(:/beijing.jpg);}QLineEdit {color:rgb(8, 8, 8);background-color:rgb(224, 255, 246);border:none;border-radius:15px;padding:0px 10px;font-size:20px;}QCheckBox {color:rgb(1, 86, 21);font: 75 13pt Bahnschrift;}QPushButton {font-size:20px;color:rgb(8, 8, 8);background-color:rgb(224, 255, 246);border-radius:15px;}QPushButton:pressed {color:rgb(255, 137, 41);background-color:rgb(103, 150, 185);}运行2. 绘图2.1 基本概念虽然 Qt 已经内置了很多的控件, 但是不能保证现有控件就可以应对所有场景.很多时候我们需要更强的 ⾃定制 能力.Qt 提供了画图相关的 API, 可以允许我们在窗⼝上绘制任意的图形形状, 来完成更复杂的界⾯设计.所谓的 控件 , 本质上也是通过画图的⽅式画上去的.画图 API 和 控件 之间的关系, 可以类⽐成机器指令和⾼级语⾔之间的关系.控件是对画图 API 的进⼀步封装; 画图 API 是控件的底层实现.绘图 API 核心类类说明QPainter绘画者 或者 画家.⽤来绘图的对象, 提供了⼀系列 drawXXX 方法, 可以允许我们绘制各种图形.QPaintDevice画板.描述了 QPainter 把图形画到哪个对象上. 像咱们之前用过的 QWidget 也是⼀种 QPaintDevice (QWidget 是 QPaintDevice 的⼦类) .QPen画笔.描述了 QPainter 画出来的线是什么样的.QBrush画刷.描述了 QPainter 填充⼀个区域是什么样的.绘图 API 的使⽤, ⼀般不会在 QWidget 的构造函数中使⽤, 而是要放到 paintEvent 事件中.paintEvent 会在以下情况下被触发:控件首次创建.比如在QWidget上画画QWidget 创建之前画的东西当然的不生效首次创建 QWidget 就能显示出话的东西来控件被遮挡, 再解除遮挡.这个时机进行绘制也是很重要的否则绘制的内容就会在被遮挡之后就没了窗口最小化, 再恢复.窗口最小化, 再恢复.控件大小发⽣变化时.主动调⽤ repaint() 或者 update() 方法. (这两个方法都是 QWidget 的方法).......因此, 如果把绘图 api 放到构造函数中调⽤, 那么⼀旦出现上述的情况, 界⾯的绘制效果就无法 确保符合预期了.2.2 绘制各种形状2.2.1 绘制线段inline void QPainter::drawLine(int x1, int y1, int x2, int y2){QLine l(x1, y1, x2, y2);drawLines(l, 1);}运行运行2.2.2 绘制矩形运行2.2.3 绘制圆形inline void QPainter::drawEllipse(int x, int y, int w, int h){drawEllipse(QRect(x, y, w, h));}int w, int h是外接矩形的宽度高度运行也可以画椭圆运行2.2.4 绘制文本此处的 20 横坐标表示的是 文字最左侧的位置此处的 100 纵坐标表示的是文字的“基线位置”基线位置运行坐标写成00 的话就会看不见文本运行2.2.5 设置画笔QPainter 在绘制时是有⼀个默认的画笔的。在使⽤时也可以⾃定义画笔。在 Qt 中QPen类中定义了 QPainter 应该如何绘制形状、线条和轮廓。同时通过 QPen类 可以设置画笔的线宽、颜⾊、样式、画刷等。画笔的颜⾊可以在实例化画笔对象时进⾏设置画笔的宽度是通过 setWidth() ⽅法进⾏设置画笔的⻛格是通过setStyle(⽅法进⾏设置设置画刷主要是通过 setBrush() ⽅法。设置画笔颜⾊QPen::QPen(const QColor color) 画笔的颜⾊主要是通过 QColor 类设置设置画笔宽度void QPen::setWidth(int width)设置画笔⻛格void QPen::setStyle(Qt::PenStyle style)画笔的⻛格有运行2.2.6 设置画刷在 Qt 中画刷是使⽤ QBrush类 来描述画刷⼤多⽤于填充。QBrush定义了QPainter的填充模式具有样式、颜⾊、渐变以及纹理等属性。画刷的格式中定义了填充的样式使⽤ Qt::BrushStyle 枚举默认值是 Qt::NoBrush也就是不进⾏任何填充。可以通过 Qt 助⼿查找画刷的格式。如下图示如果只指定颜色的话是不起效果同时还要设置风格才能起效。运行运行2.3 绘制图片Qt 提供了四个类来处理图像数据QImage、QPixmap、QBitmap 和 QPicture它们都是常⽤的绘图设备。其中QImage主要⽤来进⾏ I/O 处理它对 I/O 处理操作进⾏了优化⽽且可以⽤来直接访问和操作像素QPixmap 主要⽤来在屏幕上显⽰图像它对在屏幕上显⽰图像进⾏了优化QBitmap是 QPixmap 的⼦类⽤来处理颜⾊深度为1的图像即只能显⽰⿊⽩两种颜⾊QPicture ⽤来记录并重演 QPainter 命令。这里只讲解 QPixmap。2.3.1 图片的缩放导入图片运行2.3.2 图片的旋转图片的旋转本质上就是把 QPainter 对象进行了旋转绘制出来的内容也就产生了旋转运行啥也没有。原因是绕着 00坐标系原点进行的旋转。为了将图片显示出来可以把坐标系的原点平移一下平移到窗口的右下角。此时往右移动 x 减小往下移动 y 减小运行
返回列表