控件 QWidget
- 一. 控件概述
- 二. QWidget 的核心属性
- 可用状态:enabled
- 几何:geometry
- windows frame 窗口框架的影响
- 窗口标题:windowTitle
- 窗口图标:windowIcon
- qrc 机制
- 窗口不透明度:windowOpacity
- 光标:cursor
- 字体:font
- 工具提示:toolTip
- 焦点策略:focusPolicy
- 样式表:styleSheet
- 三. QWidget 属性小结
一. 控件概述
编程,讲究的是 “站在巨人的肩膀上”,而不是 “从头发明轮子”。
- Widget 是 Qt 中的核心概念,英文原义是 “小部件”,我们此处也把它翻译为 “控件”,控件是构成一个图形化界面的基本要素。
- 一个图形化界面上的内容,不需要我们全都从零去实现,Qt 中已经提供了很多内置的控件了 (按钮、文本框、单选按钮、复选按钮、下拉框),我们拿过来就可以使用。
- 上古时期,开发 GUI,没啥控件概念,界面上显示出来的东西,全部都是 “画” 出来的。
- 显示器显示的内容,可以理解成 “画布”,操作系统,就可以提供一些 API,让你在 “画布” 上进行画点、线、矩形、三角形等等,以及填充各种颜色。
- 这个时候,开发一个图形化界面的程序,就相当于先画出一个矩形窗口。
- 这种风格的开发,其实已经非常古老了。
- 后来,控件这样的概念就逐渐被引入了,早起的控件比较简单,数量页比较有限。
- 例如:HTML,包含很多标签,不同的标签有不同的效果。
- 图片:< img >、链接:< a >、输入框:< input >、按钮:< button >
- 例如:HTML,包含很多标签,不同的标签有不同的效果。
- 随着时代的发展,新的 GUI 开发体系越来越丰富,提供的控件数量/质量越来越好了。
- 例如:前端开发的知名框架 Element,整体来说,种类和效果都大幅度的提升了。
- Qt 的控件虽然很多,但是整体来说,颜值还是比更现代的控件体系,要逊色一些。
- Qt Designed 中展示的控件都是默认的样子。
- Qt 还提供了一些优化手段,可以让控件变得更好看。
- Qt 近几年还提供了 Qt Design Studio,对标的就是现代化的界面体系,制作出来的界面的美观程度就是业界最领先的一档,但是时要收费的。
- 开发图形化界面程序,颜值确实还是一个挺重要的事情,往往会有专业的美工,先来设计更好看的界面,再交给程序员实现出来。
- Qt 作为一个成熟的 GUI 开发框架,内置了大量的常用控件,如下图。
- 这一点在 Qt Designer 中就可以看到端倪。
- Qt 也提供了 “自定义控件” 的能力,可以让程序员在现有控件不能满足需求的时候,对现有控件做出扩展,或者手搓出新的控件。
综上,学习 Qt,其中一个很重要的任务就是熟悉并掌握 Qt 内置的常用控件,这些控件对于我们快速开发出符合需求的界面,是至关重要的。
二. QWidget 的核心属性
在 Qt 中,使用 QWidget 类表示 “控件”
- 像按钮,视图,输入框,滚动条等具体的控件类,都是继承 QWidget
- 可以说,QWidget 中就包含了 Qt 整个控件体系中,通用的部分。
在 Qt Designer 中,随便拖一个控件过来,选中该控件,即可在右下方看到 QWidget 中的属性。
- 这些属性既可以通过 Qt Designer 直接修改,也可以通过代码的方式修改。
- 这些属性的具体含义,在 Qt Assistant 中均有详细介绍。
- 在 Qt Assistant 中搜索 QWidget,即可找到对应的文档说明
- 或者在 Qt Creator 代码中,选中 QWidget,按 F1 也可。
可用状态:enabled
API | 说明 |
---|---|
isEnabled() | 获取控件的可用状态 |
setEnabled() | 设置控件是否可使用。true 表示可用,false 表示禁用 |
- 所谓 “禁用” 指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。
- 如果一个 Widget 被禁用,则该 Widget 的子元素也被禁用。
代码:创建一个禁用状态的按钮。
代码:通过按钮2,切换按钮1为的可用状态。
在同一个界面中,要求不同的控件的 objectName 也是必须是不同的,后续就可以通过 ui->objectName 方式来获取到对应的控件对象了,以下是通过拖拽的方式添加按钮控件,且自动生成控件对象的名称。
- ui->pushButton 这是第一个按钮控件对象。
- ui->pushButton_2 这是第二个按钮控件对象。
- 元编程:Qt Designer 生成的 widget.ui 文件,本身是 XML 格式的,qmake 会把这个 XML 文件转换成 C++ 的 ui_widget.h 文件,生成的过程中就会感知到,界面上都存在哪些控件,且为每一个控件设置一个 objectName
- 当前自动生成的 objectName 存在规律:控件类型_数字。很明显,以数字的方式命名,并不是一个好的编程习惯,我们也可以修改控件的名称。
右键点击两个按钮,点击转到槽,为 clicked 信号添加槽函数,此时不需要 connect
- QPushButton 提供的信号还是挺多的,最常用的就是 clicked,它存在两个版本。
- 无参版本:一般对于 QPushButton 来说,使用无参版本即可。
- 有参版本:参数 bool check,表示是否被勾选,这个东西对于 QPushButton 没有意义。
最终结果:点击第一个按钮,执行对应的槽函数,点击第二个按钮,执行对应的槽函数 (若第一个按钮是可用的,则设置禁用,若第一个按钮是禁用的,则设置可用)
几何:geometry
geometry:几何,位置和尺寸,其实是四个属性的统称:
- x:横坐标。
- y:纵坐标。
- width:宽度。
- height:高度。
但是实际开发中,我们并不会直接使用这几个属性,而是通过一系列封装的方法来获取/修改。对于 Qt 的坐标系,不要忘记是一个 “左手坐标系”,其中坐标系的原点是当前元素的父元素的左上角。
API | 说明 |
---|---|
geometry | 获取到控件的位置和尺寸。返回结果是一个 QRect (矩形),包含了 x、y、width、height。其中 x、y 是左上角的坐标 |
setGeometry(QRect) | 设置控件的位置和尺寸,可以直接设置一个 QRect |
setGeometry(int x, int y, int width, int height) | 设置控件的位置和尺寸,也可以分四个属性单独设置 |
move 只是修改控件的位置,setGeometry 修改控件的位置和尺寸。
控制按钮的位置
五个按钮的 objectName 分别为 pushButton_target、pushButton_up、pushButton_down、pushButton_left、pushButton_right,且五个按钮的初始位置和大小都随意。
- 修改控件的名称时,需要点击那个控件,然后在 objectName 后面,写上你要的名称。
添加上下左右,这四个按钮的点击信号对应的槽函数,并补全代码如下:
- qDebug() << rect 输出的结果:(x, y, width*height)
- 最终效果:疯狂点击 left 和 up,达到的效果是,按钮的左上角的位置往左上走,但是右下角的位置不变,导致高度和宽度变大了。
如果想让这个按钮能够平移 (高度和宽度不变,整个按钮的位置都发生改变):
- 上述的代码,修改的是 QRect 对象的 x 和 y,这样的修改就会使 QRect 的宽度和高度发生变换。
- 通过 QRect 基于 setGeometry 第二个版本的函数重新设置位置即可。
- 上述代码使用 move 方法也是可以的。
- 最终效果:疯狂点击 left 和 up,达到的效果是,按钮的左上角的位置和右下角的位置同时往左上走。
简单的表白程序
往界面上拖拽两个按钮 PushButton 和一个 Label,设置 PushButton 的名称为 pushButton_accept 和 pushButton_reject,并且如下图:
为按钮设置点击操作的槽函数,如下:
- rand() 是 C 标准库中能够生成随机数的函数,使用之前需要通过 time() 函数设置随机种子,C 语言中 time() 函数可以获取秒级别时间戳 (以1970年1月1日0时0分0秒为基准,计算当前时刻和基准时刻的秒数之差)
- 按钮提供的信号不止有点击 clickede (按下和松开),使用 pressed 信号,就是鼠标按下时就触发对应的槽函数。
- 也可以做到鼠标不点击,只要挪动到按钮上,就会让按钮挪动 mouseMoveEvent,需要用到 Qt 中的事件机制 (需要自定义类继承 QPushButton,重写 mouseMoveEvent 方法)
- 最终效果:按钮残忍拒绝按钮,它会乱跑。
windows frame 窗口框架的影响
- windows frame 是操作系统自带的,此时存在一个问题,按钮的位置是以父元素 Widget 窗口,还是以包含 window frame 为标准的。
- widget 作为一个窗口 (带有标题栏,最小化,最大化,,关闭按钮),那么在计算尺寸和坐标的时候就有两种算法:包含 window frame 和不包含 window frame
- 其中 x()、y()、frameGeometry()、pos()、move() 都是按照包含 window frame 的方式来计算的。
- 其中 geometry()、width()、height()、rect()、size() 则是按照不包含 window frame 的方式来计算的。
- 当然,如果是一个控件,上述两类方式得到的结果是一致的,因为它们不是一个窗口。
相关 API 如下:
API | 说明 |
---|---|
x() | 获取横坐标 (包含 window frame) |
y() | 获取纵坐标 (包含 window frame) |
pos() | 返回 QPoint 对象,里面包含 x()、y()、setX()、setY() 等方法 (包含 window frame) |
frameSize() | 返回 QSize 对象,里面包含 width()、height()、setWidth()、setHeight() 等方法 (包含 window frame) |
frameGeometry() | 返回 QRect 对象,QRect 相当于 QPoint 和 QSize 的结合体,可以获取以及设置 x、y、width、size (包含 window frame) |
width() | 获取宽度 (不包含 window frame) |
height() | 获取高度 (不包含 window frame) |
size() | 返回 QSize 对象,里面包含 width()、height()、setWidth()、setHeight() 等方法 (不包含 window frame) |
rect() | 返回 QRect 对象,QRect 相当于 QPoint 和 QSize 的结合体,可以获取以及设置 x、y、width、size (不包含 window frame) |
geometry() | 返回 QRect 对象,QRect 相当于 QPoint 和 QSize 的结合体,可以获取以及设置 x、y、width、size (不包含 window frame) |
setGeometry() | 直接设置窗口的位置和尺寸,可以设置 x、y、width、height,或者 QRect 对象 (不包含 window frame) |
其实这里的 API 有 frameGeometry 和 geometry 两个就足够完成所有的需求了。
代码:感受 geometry 和 frameGeometry 的区别。
执行程序,可以看到,构造函数中,打印出的 geometry 和 frameGeometry 是相同的,这是为什么?
- 当前代码是放到了构造函数中,此时这个 Widget 对象正在被构造,还没有加入到 window frame 中,因此,此时看不到 window frame 的影响。
如何才能看到二者的影响呢?
- 添加一个按钮,且生成一个点击信号的槽函数中,由于用户点击的时候,对象已经构造好了,此时 Widget 已经具备了 window frame,因此在位置和尺寸上均出现了差异,代码如下:
如果把上述代码修改成打印 pushButton 的 geometry 和 frameGeometry,结果就是完全相同的,因为 pushButton 并非是一个窗口。
窗口标题:windowTitle
当前 windowTitle 属性,是属于 QWidget 的,只能针对顶层窗口 Widget 才有效,其它的子 Widget,此时是无效的。
API | 说明 |
---|---|
windowTitle() | 获取控件的窗口标题 |
setWindowTitle() | 设置控件的窗口标题 |
代码:设置窗口标题
当前不应该给按钮设置窗口标题,但是实际设置了之后,没有任何效果,也没有报错,此时 “没有报错” 这样的设定是不太科学的,这一点,更希望当写出不科学代码的时候,能够给一些报错提示。
窗口图标:windowIcon
windowIcon:表示窗口图标,类似于 windowTitle,只能针对顶层窗口使用,如果对窗口中的控件使用的话,是没有效果的,如下图标:
API | 说明 |
---|---|
windowlcon() | 获取控件的窗口图标,返回 Qlcon 对象 |
setWindowTitle() | 设置控件的窗口图标 |
代码:设置窗口图标
- 之前推荐使用堆来创建对象,主要是因为要确保当前控件的生命周期是足够的,要通过 Qt 对象树来释放对象。
- QIcon 自身是一个比较小的对象,创建出来后,就是要设置到某个 QWidget 里面,QIcon 本身是否释放,不影响图标最终的显示。QIcon 也不支持对象树,无法给他指定父对象。
- Qt 封装的这些类,都会有同名的头文件。
于此同时,程序在任务栏中的图表也发生改变,如下:
路径相关的使用:
- 路径不要带有中文。
- 使用
'/'
作为路径分隔符,是否可以使用'\'
作为路径分隔符呢?'\'
是转义字符,它搭配一个字符,会存在一些特殊的含义,例如:'\r'
是回车符。- C++ 11 引入了 raw string 解决了上述问题,字符串里不包含任何转义字符,也就是所有的字符都不会转移,“d:\rose.png” 也可以是一个完整的路径。
- 但是我们更推荐使用
'/'
充当路径分隔符。
- 通过绝对路径的方式引入图片是不科学的。
- 你写的程序,最终是要发布到用户的电脑上的,你无法确保,你开发机上的图片的路径和用户电脑上的图片的路径完全一致。
- 比如:我们开发的程序是把图片放到 D 盘上,但是用户的电脑上没有 D 盘,此时就找不到图片。
- 你写的程序,最终是要发布到用户的电脑上的,你无法确保,你开发机上的图片的路径和用户电脑上的图片的路径完全一致。
- 因此,使用相对路径的方式,使用相对路径是更好的。
- 相对路径:是以给点目录为基准,以
.
或者..
的方式开头。 - 假设基准目录是 D:/
- 给定相对路径是 ./rose.png:在基准目录 D:/ 中直接查找 rose.png
- 给定相对路径是 ./image/rose.png:在基准目录 D:/ 中,先进入 image 目录,再直接查找 rose.png
- 相对路径:是以给点目录为基准,以
qrc 机制
万一用户不小心把图片资源删除了,如何办呢?
- qrc 机制可以从根本上,解决以下问题:
- 确保你的图片所在的路径在目标用户的机器上存在。
- 确保你的图片不会被用户搞没了。
qrc 机制介绍:
- qrc 文件是一种 XML 格式的资源配置文件 (后缀名使用 .qrc 表示),它用 XML 记录硬盘上的文件和对应的随意指定的资源名称,应用程序通过资源名称来访问这些资源。
- 在 Qt 开发中,可以通过将资源文件添加到项目中来方便地访问和管理这些资源,这些资源文件可以位于 qrc 文件所在目录的同级或其子目录下。
- Qt 在编译项目的时候,就会根据 qrc 中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转换成 C++ 代码,最终编译到 exe 里面,从而使依赖的资源变得 “与路径无关”。
- qrc 缺点:无法导入太大的资源文件。
- 比如:搞几个 GB 这种视频文件,就不太合适了,qrc 无能为力。
- 这种资源管理机制并非 Qt 独有,很多开发框架都有类似的机制。例如 Android 的 Resources 和 AssetManager 也是类似的效果。
qrc 使用方式
在项目中创建一个 qrc 文件,文件名不要带中文和特殊符号:
把图片导入到 qrc 文件中:
-
点击 Add Prefix 先创建一个 “前缀”,把 前缀的名字修改为 / 即可,如下:
- 所谓的 “前缀” 可以理解为虚拟的目录,这个目录在你的电脑上不是真实存在,为了方便 Qt 代码访问到这个图片,它是 Qt 自己抽象出来的。
- qrc 机制本质就是把图片的二进制数据,转换成 C++ 代码,最终就会在代码中看到很大的 char 数组,里面就是图片的二进制数据。
-
把图片 rose.png 导入到资源文件中,也就是点击 Add Files
- Add Files 这个按钮在创建 Prefix 之前是禁用的,创建好 Prefix 之后就可以使用了,添加的文件就是添加到 Prefix 下面。
- 点击 Add Files 得到的目录,就是当前代码所在的目录。
- 导入图片的时候,需要确保你导入的图片必须在 resource.qrc 文件的同级目录,或者同级目录中的子目录里面。
- 因此就可以把 rose.png 拷贝到当前项目中即可,再选中 rose.png 导入进来即可。
- 看到这个效果就说明导入成功了。
- 当我们代码中需要访问 qrc 中管理文件的时候,就需要在路径中带有
冒号前缀
,创建的前缀叫啥名字,代码中就写啥名字。 - qrc 导入的图片资源,就会自动转换成 qrc_resource.cpp 文件,这里的字节内容就是 rose.png 里的每个字节的数据,内容如下:
- 当 Qt 项目进行编译的时候,这个 .cpp 文件就一起编译到了 exe 中,当 exe 程序运行的时候,图片的数据也就加载到内存中了。
窗口不透明度:windowOpacity
API | 说明 |
---|---|
windowOpacity() | 获取控件的不透明数值,返回 float,取值为0.1~1.0,其中0.0表示全透明,1.0表示完全不透明 |
setWindowOpacity() | 设置控件的不透明数值 |
代码:调整窗口透明度
在界面上拖放两个按钮,分别用来增加不透明度和减少不透明度 objectName 分别是 pushButton_add 和 pushButton_sub:
编写 wdiget.cpp,编写两个按钮的 slot 函数:
- 点击 pushButton_sub 会减少不透明度,也就是窗口越来越透明。
- 点击 pushButton_add 会增加不透明度,窗口会逐渐恢复。
两个问题:
- 窗口的不透明度,变化并非是精确的。
- 整数在内存中的存储。
- 原码反码补码,字节序。
- 浮点数在内存中的存储。
- 遵守 IEEE 754 标准,使用二进制科学计数法的方式。
- 优点:运算速度快,占用空间小 (CPU 制造的时候,针对这种运算专门优化的)
- 缺点:对于一些小数无法精确表示。
- 平时写代码的时候,千万不要把两个浮点数直接使用,例如:0.1+0.2==0.3,这样是错误的,正确写法是:作差,判定差的绝对值小于预期的误差范围。
- 后续工作中编写代码的时候,尤其是涉及到一个需要精确计算的场景,比如:算钱,一定要慎重使用 float 和 double!
- 整数在内存中的存储。
- 上述代码中,在进行设置之前,先判定 opacity 的范围,然后再决定是否要设置,这个判定其实是可以不写的 (setWindoeOpacity 内部进行了判定),为什么我们要写上?
- “防御性编程”:很多写代码的时候,往往是把一个大的项目分成几个模块,有不同的人去完成,模块之间要进行交互,往往一个模块的 API 要给另一个模块调用。
- 你在使用别人提供的 API 来进行调用的时候,你是否要对传入的参数进行检查呢?
- 比如你要传入一个实参,你也不知道这个参数是否是一个 nullptr,是否应该在调用函数之前,先进行判空,还是 API 内部已经进行了判空,你不再需要判空,这是不知道的。
- 最好的办法就是,在调用 API 之前进行判空,可以做到即便 API 没有进行判空操作,问题也不大。
- “防御性编程”:很多写代码的时候,往往是把一个大的项目分成几个模块,有不同的人去完成,模块之间要进行交互,往往一个模块的 API 要给另一个模块调用。
光标:cursor
API | 说明 |
---|---|
cursor() | 获取控件的光标形状,返回 QCursor 对象 |
setCursor() | 设置控件的光标形状,当鼠标停留在该控件上,就会显示出对应的形状 |
QGuiApplication::setOverrideCursor() | 设置全局光标的形状,对整个程序中的所有控件都会生效,覆盖上main的 setCursor 设置的内容 |
- 同一个界面中,不同的控件可以设置成不同的光标。
- 这里的设置全局光标,是程序内的全局,而不是系统级别的全局。
代码:在 Qt Designer 中设置按钮的光标
截图无法看到光标,运行程序,鼠标悬停到按钮上,即可看到光标会变成一个打开手势。
代码:通过代码设置按钮的光标
运行程序,鼠标悬停到按钮上,即可看到光标会变成一个 “转圈圈的状态”。
Ctrl + 左键点击 Qt::WaitCursor 跳转到源码,即可看到系统内置的光标形状如下:
代码:自定义鼠标光标
Qt 自带的光标形状有限,我们也可以自己找个图片,做成鼠标的光标,这里使用了一个滑稽。
- 创建 qrc 资源文件,添加前缀 /,并加入 funny.png
- 编写 widget.cpp,在代码中访问到这个图片,先构造图片对象 (QPixmap),再基于这个图片对象构造出光标对象 (QCursor)
- pixmap = pixmap.scaled(50, 50):通过这个函数对图片进行缩放,但是缩放并不是修改图片本身,而是返回一个新的图片对象副本。
- QCursor cursor(pixmap, 10, 10):默认情况下,鼠标点击是,相当于图片的左上角在进行点击,加上该代码的意思是,一图片左上角为 (0, 0) 原点,找到 (10, 10) 这个位置作为鼠标真正点击的位置。
- 免费的图标获取网站:阿里巴巴矢量图标库 https://www.iconfont.cn/
字体:font
API | 说明 |
---|---|
font() | 获取当前 Widget 的字体信息,返回 QFont 对象 |
setFont() | 设置当前 Widget 的字体信息 |
关于 QFont
属性 | 说明 |
---|---|
family | 字体家族,比如:“楷体”、“宋体”、“微软雅黑” 等 |
pointSize | 字体大小 |
weight | 字体粗细,以数值方式表示粗细程度取值范围 [0, 99],数值越大,越粗 |
bold | 是否加粗,设置为 true 相当于 weight 为 75,设置为 false 相当于 weight 为 50 |
italic | 是否倾斜 |
underline | 是否带有下划线 |
strikeOut | 是否带有删除线 |
上述属性具体怎么设置,实际开发中,往往有专门的 美工/设计/UED 来进行确定。
- 但是如果是一些小公司,没有美工,甚至没有产品经理,这个情况,我们作为一个程序员,就可以参考一下别人的程序是怎么安排的,或者别人写的网页时怎么安排的。
代码:在 Qt Designer 中设置字体属性
在界面上创建一个 label 控件,在右侧的属性编辑区,设置该 label 的 font 相关属性。
- 在 Qt Designer 调整上述属性,可以实时的看到文字的变化。
- 通过属性编辑这样的方式,虽然能够快速方便的修改文字相关的属性,但是还是不够灵活,如果程序运行过程中,需要修改文字的属性,就需要通过代码来操作了。
代码:在代码中设置字体属性
工具提示:toolTip
一个 GUI 程序,界面比较复杂,按钮啥的很多,当你把鼠标悬停在这个控件上的时候,就能弹出一个提示。
API | 说明 |
---|---|
setToolTip() | 设置 toolTip,鼠标悬停在该 Widget 上时会有提示说明 |
setToolTipDuring() | 设置 toolTip 提示的事件,单位 ms,时间到后 toolTip 自动消失 |
注意:toolTip 只是给用户看的,在代码中一般不需要获取到 toolTip
代码:设置按钮的 toolTip
在界面上拖放两个按钮,objectName 设置为 pushButton_yes 和 pushButton_no,如下图:
编写 widget.cpp 文件,运行程序后,可以看到鼠标停到按钮上之后,就能弹出提示,时间到后自动消失,如下图:
焦点策略:focusPolicy
设置控件获取到焦点的策略,比如某个控件能否用鼠标选中或者能否通过 tab 键选中。
- 所谓 “焦点”,指的就是能选中这个元素,接下来的操作 (比如键盘操作),就都是针对该焦点元素进行的了,这个对于 输入框,单选框,复选框等控件非常有用的。
- GUI 中,窗口/控件,焦点是非常关键的。
- 线上笔试、笔试链接,点击链接,打开一个网站,就可以在线做题了,你在人家的网页中去做题,网页是属于时钟获取到焦点的状态的,你一旦切换到百度/其他程序 (VS) 时,立刻人家的网页就能感知到 “失去焦点”,服务器就能收集到你这样的动作,从而衡量你是否涉嫌作弊。
- 这些线上笔试平台,反作弊机制非常成熟,例如:牛客、赛码;即便是得分低,也有可能通过笔试,一旦作弊,一定通过不了笔试的,甚至可能被公司拉黑。
API | 说明 |
---|---|
focusPolicy() | 获取该 widget 的 focusPolicy,返回 Qt::FocusPolicy |
setFocusPolicy() | 设置 widget 的 focusPolicy |
Qt::FocusPolicy 是一个枚举类型,取值如下:
- Qt::NoFocus:控件不会接收键盘焦点。
- Qt::TabFocus:控件可以通过 Tab 键接收焦点。
- Qt::ClickFocus:控件在鼠标点击时接收焦点。
- Qt::StrongFocus:控件可以通过 Tab 键和鼠标点击接收焦点 (默认值)
- Qt::WheelFocus:类似于 Qt::StrongFocus,同时控件也通过鼠标滚轮获取到焦点 (新增的选项,一般很少使用)
代码:理解不同的 focusPolicy
在界面上创建四个单行输入框 (Line Edit),修改四个输入框的 focusPolicy 属性为 Qt::StrongFocus (默认取值,一般不用额外修改),如下图:
此时运行程序后可以看到,使用鼠标单击/tab,就可以移动光标所在输入框,从而接下来的输入就是针对这个获取焦点的输入框展开的了。
-
修改第二个输⼊框的 focusPolicy 为 Qt::NoFocus,则第二个输入框不会被 tab / 鼠标左键选中,此时这个输入框也就无法输入内容了。
-
修改第二个输入框 focusPolicy 为 Qt::TabFocus,则只能通过 tab 选中,无法通过鼠标选中。
-
修改第二个输入框 focusPolicy 为 Qt::ClickFocus,则只能通过 鼠标 选中,无法通过 tab 选中。
样式表:styleSheet
通过 CSS 设置 Widget 的样式。
- 层叠样式表 (CSS):在进行网页前端开发的时候,设置了网页样式的方式。
- CSS 这个东西发展了多年,已经非常成熟了,能够提供非常丰富的功能,把网页能设置成非常好看。
- 样式:描述了界面具体是什么样子的,包括但不限于大小、位置、颜色、间距、字体、背景、边框等。
- 我们平常看到的丰富多彩的网页,都会大量使用到 CSS
- Qt 虽然是做 GUI 开发,但是实际上和网页前端有很多异曲同工之妙,因此 Qt 就把 CSS 参考过来了,搞了一套 QSS,虽然相比于 CSS 功能上缺失很多,即使如此也能够帮我们完成不少效果。
代码:设置文本样式
在界面上创建 Label,编辑右侧的 styleSheet 属性,点击三个点,如下:
开始设置样式,效果如下图:
- 和 CSS 类似,QSS 设置的样式也是 “键值对” 的格式,键和值之间用 冒号 分隔,键值对和键值对之间用 封号 分隔。
- 具体怎么设置,可以在 Qt 文档中,搜索 QtStyleSheet
代码:通过代码来设置样式,实现一个 “夜间模式” 功能
- 日间模式:文字是黑色,背景是白色。
- 夜间模式:文字是白色,背景是黑色。
在界面上创建一个多行输入框 (TextEdit) 和两个按钮,objectName 分别为 pushButton_light 和 pushButton_dark,如下:
右击两个按钮,点击 “转到槽”,自动生成点击按钮信号的槽函数,编写代码实现 “日夜切换”,如下:
千万要注意这里的单词拼写,不要出错,否则不会有任何报错,但是样式不会失效。
运行代码,向输入框中输入一些文字,如下:
点击两个按钮,效果如下:
如何获取具体的颜色 RGB 呢?可以使用 QQ 截图的功能,如下:
三. QWidget 属性小结
下列表格列出了 QWidget 中的属性及其作用: