【Qt】控件 QWidget
控件 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 中的属性及其作用:
相关文章:

【Qt】控件 QWidget
控件 QWidget 一. 控件概述二. QWidget 的核心属性可用状态:enabled几何:geometrywindows frame 窗口框架的影响 窗口标题:windowTitle窗口图标:windowIconqrc 机制 窗口不透明度:windowOpacity光标:cursor…...

Linux入门课的思维导图
耗时两周,终于把慕课网上的Linux的基础入门课实操、总结完了! 第一次以Blog的形式做学习记录,过程很有意思,但也很耗时。 课程时长5h,涉及到很多专有名词,要去逐个查找,以前接触过的概念因为时…...

aurora与pcie的数据高速传输
设备:zynq7100; 开发环境:window; vivado版本:2021.1; 引言 之前在前面两章已经介绍了aurora读写DDR,xdma读写ddr实验。这次我们做一个大工程,pc通过pcie传输给fpga,fpga再通过aur…...

Springboot 高校报修与互助平台小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,高校报修与互助平台小程序被用户普遍使用,为…...

Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用
Linux 内存管理调试分析:ftrace、perf、crash 的系统化使用 Linux 内核内存管理是构成整个内核性能和系统稳定性的基础,但这一子系统结构复杂,常常有设置失败、性能展示不良、OOM 杀进程等问题。要分析这些问题,需要一套工具化、…...

MLP实战二:MLP 实现图像数字多分类
任务 实战(二):MLP 实现图像多分类 基于 mnist 数据集,建立 mlp 模型,实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入,可视化图形数字; 2、完成数据预处理:图像数据维度转换与…...

【汇编逆向系列】六、函数调用包含多个参数之多个整型-参数压栈顺序,rcx,rdx,r8,r9寄存器
从本章节开始,进入到函数有多个参数的情况,前面几个章节中介绍了整型和浮点型使用了不同的寄存器在进行函数传参,ECX是整型的第一个参数的寄存器,那么多个参数的情况下函数如何传参,下面展开介绍参数为整型时候的几种情…...
C#最佳实践:为何优先使用as或is而非强制转换
C#最佳实践:为何优先使用as或is而非强制转换 在 C# 的编程世界里,类型转换是我们经常会遇到的操作。就像在现实生活中,我们可能需要把不同形状的物品重新整理归类一样,在代码里,我们也常常需要将一个数据类型转换为另…...

PLC入门【4】基本指令2(SET RST)
04 基本指令2 PLC编程第四课基本指令(2) 1、运用上接课所学的基本指令完成个简单的实例编程。 2、学习SET--置位指令 3、RST--复位指令 打开软件(FX-TRN-BEG-C),从 文件 - 主画面,“B: 让我们学习基本的”- “B-3.控制优先程序”。 点击“梯形图编辑”…...

react更新页面数据,操作页面,双向数据绑定
// 路由不是组件的直接跳转use client,useEffect,useRouter,需3个结合, use client表示客户端 use client; import { Button,Card, Space,Tag,Table,message,Input } from antd; import { useEffect,useState } from react; impor…...
PostgreSQL 与 SQL 基础:为 Fast API 打下数据基础
在构建任何动态、数据驱动的Web API时,一个稳定高效的数据存储方案是不可或缺的。对于使用Python FastAPI的开发者来说,深入理解关系型数据库的工作原理、掌握SQL这门与数据库“对话”的语言,以及学会如何在Python中操作数据库,是…...

Python异步编程:深入理解协程的原理与实践指南
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 持续学习,不断…...

Ray框架:分布式AI训练与调参实践
Ray框架:分布式AI训练与调参实践 系统化学习人工智能网站(收藏):https://www.captainbed.cn/flu 文章目录 Ray框架:分布式AI训练与调参实践摘要引言框架架构解析1. 核心组件设计2. 关键技术实现2.1 动态资源调度2.2 …...

基于小程序老人监护管理系统源码数据库文档
摘 要 近年来,随着我国人口老龄化问题日益严重,独居和居住养老机构的的老年人数量越来越多。而随着老年人数量的逐步增长,随之而来的是日益突出的老年人问题,尤其是老年人的健康问题,尤其是老年人产生健康问题后&…...
el-amap-bezier-curve运用及线弧度设置
文章目录 简介示例线弧度属性主要弧度相关属性其他相关样式属性完整示例链接简介 el-amap-bezier-curve 是 Vue-Amap 组件库中的一个组件,用于在 高德地图 上绘制贝塞尔曲线。 基本用法属性path定义曲线的路径,可以是多个弧线段的组合。stroke-weight线条的宽度。stroke…...
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀”
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀” 在JavaScript中,我们经常需要处理文本、数组、对象等数据类型。但当我们需要处理文件上传、图像处理、网络通信等场景时,单纯依赖字符串或数组就显得力不从心了。这时ÿ…...

理想汽车5月交付40856辆,同比增长16.7%
6月1日,理想汽车官方宣布,5月交付新车40856辆,同比增长16.7%。截至2025年5月31日,理想汽车历史累计交付量为1301531辆。 官方表示,理想L系列智能焕新版在5月正式发布,全系产品力有显著的提升,每…...
Linux中INADDR_ANY详解
在Linux网络编程中,INADDR_ANY 是一个特殊的IPv4地址常量(定义在 <netinet/in.h> 头文件中),用于表示绑定到所有可用网络接口的地址。它是服务器程序中的常见用法,允许套接字监听所有本地IP地址上的连接请求。 关…...

运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.
报错 找到package.json文件 找到这个修改成 "lint": "eslint --fix --ext .js,.vue src" 为elsint有配置结尾换行符,最后运行:npm run lint --fix...
java+webstock
maven依赖 <dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.5</version></dependency><dependency><groupId>org.apache.tomcat.websocket</groupId&…...
STL 2迭代器
文章目录 1.迭代器2.输入迭代器3.输出迭代器1.插入迭代器 4.前向迭代器5.双向迭代器6.随机访问迭代器7.不同容器返回的迭代器类型1.输入 / 输出迭代器2.前向迭代器3.双向迭代器4.随机访问迭代器5.特殊迭代器适配器6.为什么 unordered_set 只提供前向迭代器? 1.迭代器…...
CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14
什么是 Pattern Matching(模式匹配) ❝ 模式匹配就是一种“描述式”的写法,不需要你手动判断、提取数据,而是直接描述你希望的数据结构是什么样子,系统自动判断并提取。❞ 你给的定义拆解: ✴ Instead of …...

智警杯备赛--excel模块
数据透视与图表制作 创建步骤 创建 1.在Excel的插入或者数据标签页下找到数据透视表的按钮 2.将数据放进“请选择单元格区域“中,点击确定 这是最终结果,但是由于环境启不了,这里用的是自己的excel,真实的环境中的excel根据实训…...
uniapp获取当前位置和经纬度信息
1.1. 获取当前位置和经纬度信息(需要配置高的SDK) 调用uni-app官方API中的uni.chooseLocation(),即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...

【多线程初阶】单例模式 指令重排序问题
文章目录 1.单例模式1)饿汉模式2)懒汉模式①.单线程版本②.多线程版本 2.分析单例模式里的线程安全问题1)饿汉模式2)懒汉模式懒汉模式是如何出现线程安全问题的 3.解决问题进一步优化加锁导致的执行效率优化预防内存可见性问题 4.解决指令重排序问题 1.单例模式 单例模式确保某…...

基于Python的气象数据分析及可视化研究
目录 一.🦁前言二.🦁开源代码与组件使用情况说明三.🦁核心功能1. ✅算法设计2. ✅PyEcharts库3. ✅Flask框架4. ✅爬虫5. ✅部署项目 四.🦁演示效果1. 管理员模块1.1 用户管理 2. 用户模块2.1 登录系统2.2 查看实时数据2.3 查看天…...

Pandas 可视化集成:数据科学家的高效绘图指南
为什么选择 Pandas 进行数据可视化? 在数据科学和分析领域,可视化是理解数据、发现模式和传达见解的关键步骤。Python 生态系统提供了多种可视化工具,如 Matplotlib、Seaborn、Plotly 等,但 Pandas 内置的可视化功能因其与数据结…...

新版NANO下载烧录过程
一、序言 搭建 Jetson 系列产品烧录系统的环境需要在电脑主机上安装 Ubuntu 系统。此处使用 18.04 LTS。 二、环境搭建 1、安装库 $ sudo apt-get install qemu-user-static$ sudo apt-get install python 搭建环境的过程需要这个应用库来将某些 NVIDIA 软件组件安装到 Je…...
Vue 实例的数据对象详解
Vue 实例的数据对象详解 在 Vue 中,数据对象是响应式系统的核心,也是组件状态的载体。理解数据对象的原理和使用方式是成为 Vue 专家的关键一步。我将从多个维度深入剖析 Vue 实例的数据对象。 一、数据对象的定义方式 1. Options API 中的定义 在 Options API 中,使用 …...

Axure Rp 11 安装、汉化、授权
Axure Rp 11 安装、汉化、授权 1、前言2、汉化2.1、汉化文件下载2.2、windows汉化流程2.3、 macOs汉化流程 3、授权 1、前言 Axure Rp 11官方下载链接:https://www.axure.com/downloadthanks 2、汉化 2.1、汉化文件下载 链接: https://pan.baidu.com/s/18Clf…...