🔥 目录
- 1. 控件概述
- 控件体系的发展阶段
- 2. QWidget 核心属性
- 2.1 核心属性概览
- 2.2 用件可用(Enabled)
- 2.3 坐标系(Geometry)
- **实例 1: 控制按钮的位置**
- 实例 2: 表白 程序
- 2.4 窗口标题(windowTiltle)
- 2.5 窗口图标(windowlcon)
- 2.6 窗口透明度(windowOpacity)
- 2.7 光标属性(cursor)
- 2.8 字体属性(QFont)
- 3. Window Frame 的影响
- Geometry 和 FrameGeometry 的区别
- 4. API 设计理念
- 5. 资源管理与路径使用
- 1、图片路径的选择
- 2、路径类型说明
- 3、构建目录的作用
- 6. qrc 文件
- 6.1 qrc 文件的特点
- 6.2 通过 qrc 管理图片作为图标
- 7. 其他
- 7.1 ToolTip 设置
- 7.2 Focus Policy 设置
- 7.3 Style Sheet(QSS)
- 8. 共勉
1. 控件概述
- Widget:Qt 中的核心概念,指图形化界面的基本构成元素(如按钮、列表视图等),即 “控件” 。
- Qt 的优势:内置大量常用控件,并支持自定义控件,便于快速开发符合需求的界面
像上面示例中的,按钮、列表视图、树形视图、单行输⼊框,多行输入框,滚动条、下拉框等等都可以称为 “控件”
- Qt 作为一个成熟的 GUI 开发框架,内置了大量的常用控件。
- 这一点在
Qt Designer
中就可以看出来,并且 Qt 也提供了 “自定义控件” 的能力,可以让我们在现有控件不能满足需求的时候,对现有控件做出扩展,或者手搓出新的控件。
🔥 所以,学习 Qt 其中一个很重要的任务就是熟悉并掌握 Qt 内置的常用控件,这些控件对于我们快速开发出符合需求的界面是至关重要的
控件体系的发展阶段
- 无控件阶段:完全没有控件。此时需要通过一些绘图 API 手动的绘制出按钮或者输入框等内容,代码编写繁琐。
(例如文曲星的 Lava 平台开发)
- 粗略控件阶段:提供基本控件,如按钮和输入框,简化了GUI开发。
(例如 html 的原生控件)
- 成熟控件体系:更完整的控件体系,基本可以覆盖到 GUI 开发中的大部分场景。(例如早期的 MFC、VB、C++ Builder、Qt、Delphi、后来的 Android SDK、Java FX、前端的各种 UI 库等)
上图是前端中的 Element-ui 中的控件概览,无论是丰富程度还是颜值,都比 Qt 自带的控件更胜一筹
QT 近几年还提供了 Qt Desiign Studio
=> 对比现代化的界面体系
- 制作的界面的美观程度是业界非常领先的
- 但是收费比较贵
2. QWidget 核心属性
-
在 Qt 中,使用 QWidget 类表示 “控件”,像按钮、视图、输入框、滚动条等具体的控件类,都是继承自 QWidget。QWidget 中包含了 Qt 整个控件体系中通用的部分。
-
在 Qt Designer 中,随便拖一个控件过来,选中该控件,即可在右下方可以看到 QWidget 中的属性。
这些属性既可以通过 QtDesigner 直接修改,也可以通过代码的方式修改。这些属性的具体含义在 Qt Assistant 中均有详细介绍。
在 Qt Assistant 中搜索 QWidget,即可找到对应的文档说明 (或者在 Qt Creator 代码中选中 QWidget,按 F1(+Fn) 也可)
2.1 核心属性概览
下面是后面我罗列出的其中一些比较重要和常用的属性,等下后面会着重进行介绍
QWidget
属性及其作用:
属性 | 作用 |
---|---|
enabled | 设置控件是否可使用。true 表示可用,false 表示禁用。 |
geometry | 控制控件的位置和尺寸,包含 x , y , width , height 四个部分。坐标是以父元素为参考进行设置的。 |
windowTitle | 设置 widget 的标题。 |
windowIcon | 设置 widget 的图标。 |
windowOpacity | 设置 widget 的透明度。 |
cursor | 设置鼠标悬停时显示的图标形状,如普通箭头、沙漏或十字等。可通过 Qt Designer 查看选项。 |
font | 控制字体相关属性,包括字体家族、大小、粗体、斜体、下划线等样式。 |
toolTip | 当鼠标悬停在 widget 上时,在状态栏中显示的提示信息。 |
toolTipDuration | toolTip 显示的持续时间。 |
statusTip | 当 widget 状态发生改变时(如按钮被按下)显示的提示信息。 |
whatsThis | 当鼠标悬停并按下 Alt+F1 时,显示的帮助信息(显示在一个弹出窗口中)。 |
styleSheet | 允许使用 CSS 来设置 widget 中的样式,支持丰富的样式,便于前端开发者上手。 |
focusPolicy | 定义 widget 如何获取焦点:NoFocus , TabFocus , ClickFocus , StrongFocus , WheelFocus 。 |
contextMenuPolicy | 设置上下文菜单的显示策略:DefaultContextMenu , NoContextMenu , PreventContextMenu , ActionsContextMenu , CustomContextMenu 。 |
ocale | 设置语言和国家地区。 |
acceptDrops | 设置该部件是否接受拖放操作。true 表示可以接收来自其他部件的拖放操作;false 则表示不接收任何拖放操作。 |
minimumSize | 控件的最小尺寸,包含最小宽度和最小高度。 |
maximumSize | 控件的最大尺寸,包含最大宽度和最大高度。 |
sizePolicy | 设置控件在布局管理器中的缩放方式。 |
windowModality | 指定窗口是否具有 “模态” 行为。 |
sizeIncrement | 拖动窗口大小时的增量单位。 |
baseSize | 窗口的基础大小,用于配合 sizeIncrement 调整组件尺寸。 |
palette | 设置 widget 的颜色风格。 |
mouseTracking | 是否跟踪鼠标移动事件。true 表示需要跟踪;false 表示不需要跟踪。 |
tabletTracking | 是否跟踪触摸屏的移动事件,类似于 mouseTracking 。Qt 5.9 引入的新属性 |
layoutDirection | 设置布局方向:LeftToRight , RightToLeft , LayoutDirectionAuto 。 |
autoFillBackground | 是否自动填充背景颜色。 |
windowFilePath | 将 widget 和一个本地文件路径关联起来。 |
accessibleName | 设置 widget 的可访问名称,辅助技术(如屏幕阅读器)可以获取到这个名称。 |
accessibleDescription | 设置 widget 的详细描述,作用同 accessibleName 。 |
inputMethodHints | 针对输入框有效,用来提示用户当前能输入的合法数据格式,如只能输入数字、只能输入日期等。 |
2.2 用件可用(Enabled)
API | 说明 |
---|---|
isEnabled() | 获取到控件的可用状态 |
setEnabled() | 设置控件是否可使用,code 表示可用,false 表示禁用 |
- 所谓 “禁用” 指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。
- 如果一个
widget
被禁用,则该widget
的子元素也被禁用。
🧀 案例1:创建一个禁用状态的按钮:
运行程序,可以看到按钮处于灰色状态,无法被点击:
🧀 通过按钮 2 切换按钮 1 的禁用状态
(1)使用 Qt Designer 拖两个按钮到 Widget 中
- 两个按钮的
objectName
分别为pushButton
和pushButton_2
QObject 的 objectName 属性介绍:
QObject
是QWidget
的父类,里面最主要的属性就是objectName
。在一个 Qt 程序中,objectName
相当于对象的身份标识,彼此之间不能重复。- 在使用
Qt Designer
时,尤其是界面上存在多个widget
的时候,可以通过objectName
获取到指定的 widget 对象。 Qt Designer
生成的 ui 文件,本身是 xml 格式的,qmake
会把这个 xml 文件转换成 C++ 的 .h 文件(这个文件生成在 build 目录中),构成一个 ui_widget 类。- 每个
widget
的objectName
最终就会成为ui_widget
类的属性名字。最终这个类的实例就是:Ui::Widget *ui
,因此就可以通过形如ui->pushButton
或者ui->pushButton_2
这样的代码获取到界面上的 widget 对象了。 - 当前自动生成的
objectName
是有规律的:控件的类型 + 下划线 + 数字。很明显,以数字的方式命名并不是一个好的编程习惯,这里我将它修改为如下所示:
(2)生成两个按钮的 slot 函数
- 使用 isEnabled 获取当前按钮的可用状态。
- 使用 setEnabled 修改按钮的可用状态,此处是直接针对原来的可用状态进行取反后设置。
运行程序可以看到:初始情况下,上面的按钮是可用状态。接着点击下方按钮,即可使上方按钮被禁用
- 在
Qt Designer
中创建按钮的时候可以设置按钮的初始状态是 “可用” 还是 “禁用”。如果把enabled
这一列的对钩去掉,则按钮的初始状态就是 “禁用” 状态。
2.3 坐标系(Geometry)
位置和尺寸是四个属性的统称:
- x 横坐标
- y 纵坐标
- width 宽度
- height 高度
在实际开发中,我们通常不会直接使用这四个属性来获取或修改控件的位置和大小。
Qt
提供了一系列封装的方法,这些方法更方便操作,并且考虑到了 Qt
的左手坐标系——其中原点位于父元素的左上角。
API | 说明 |
---|---|
geometry() | 获取到控件的位置和尺寸,返回结果是一个QRect,包含 x, y, width, height,其中 x, y 是左上角坐标 |
setGeometry(QRect) seGeometry(int x, int y, int width, int height) | 设置控件的位置和尺寸,可以直接设置一个 QRect,也可以分四个属性单独设置 |
💡 move VS setGeometry
move
只是修改位置setGeometry
既可以修改位置,又可以修改尺寸
实例 1: 控制按钮的位置
① 创建界面布局:
- 在界面上拖拽五个按钮,分别命名为
pushButton_target(目标按钮)
、pushButton_up(向上移动按钮)
、pushButton_down(向下移动按钮)
、pushButton_left(向左移动按钮)
和pushButton_right(向右移动按钮)
。这些按钮的初始位置和大小可以随意设置。
② 编写槽函数:
- 在
widget.cpp
文件中为每个方向的按钮添加槽函数,用于改变pushButton_target
的位置。当点击相应的方向按钮时,会调整目标按钮的 x 和 y 坐标,从而实现位置变化 - 注意,这样做会 导致按钮的整个矩形区域发生位移,而不仅仅是其左上角
③ 优化移动逻辑:
- 如果希望按钮只移动而不改变尺寸,应该避免直接修改
QRect
对象中的 x 和 y 值。 - 相反,可以通过
setGeometry()
方法的第二个版本来重新设定按钮的位置,保持宽度和高度不变
实例 2: 表白 程序
① 设计界面:
- 向界面上添加两个按钮(接受
pushButton_forever
和拒绝pushButton_moment
)以及一个标签label
,用来显示文本信息
② 实现交互逻辑:
- 在
widget.cpp
中定义槽函数,使得当用户点击 “forever…” 拒绝按钮时,触发按钮逃跑的行为。 - 此行为可以通过监听
clicked
事件(即鼠标点击后释放)实现。
运行程序可以看到:当点击 “forever…” 时,按钮一下就跑了。
上述代码使用的是 clicked(一下一上是点击),如果使用 pressed(鼠标按下事件)。
- 这里我们需要鼠标点击才能跑,我们现在让其变成按下就跑,如下:
如果使用 mouseMoveEvent
,会更狠一些, 只要鼠标移动到这个按钮上面,按钮就跑了。
对应的代码更麻烦⼀些,需要使用到 Qt 的事件机制(需要自定义类继承自 QPushButton
,重写 mouseMoveEvent
方法)这里就暂时不展开了。
2.4 窗口标题(windowTiltle)
API | 说明 |
---|---|
windowTitle() | 获取控件的窗口标题。 |
setWindowTitle(const QString& title) | 设置控件的窗口标题 |
- 注意,仅对顶层 widget 有效,如果是 子 widget ,上该操作无效。
代码示例:设置窗口标题
2.5 窗口图标(windowlcon)
API | 说明 |
---|---|
windowIcon() | 获取控件的窗口图标,返回 QIcon 对象。 |
setWindowIcon(const QIcon& icon) | 设置控件的窗口图标。同 windowTitle ,仅对顶层 widget 有效。 |
这两个 API 类似于 windowTitle
,上述操作仅针对顶层 widget 有效。
图标网站:Yesicon 或者 iconfont-阿里巴巴矢量图标库
(1)设置窗口图标
- 先在 D 盘中保存一张图片,我这里命名为 qt_bao.jpg
- 修改
widget.cpp
-
前面推荐使用堆来创建对象 ,主要是因为要确保当前控件的生命周期是足够的,要通过 Qt 对象树来释放对象。
-
但是对于 QIcon来说,QIcon 自身是一个比较小的对象。创建出来之后,就是要设置到某个 QWidget 里面,
QIcon
对象本身是否释放并不影响图标最终的显示。 -
QIcon
也不支持对象树,无法给它执行父对象。
注意:
- 路径里面最好不要带中文
Windows
下路径的分隔符可以使用 / ,也可以使用 \- 但是如果在字符串中使用 \,需要写作转义字符的形式 \\,避免在字符串中被认为成转义字符
- 因此还是更推荐使用 /
并且程序在任务栏中的图标也发生了变化:
2.6 窗口透明度(windowOpacity)
API | 说明 |
---|---|
windowOpacity() | 获取控件的不透明数值,取值范围为 0.0(全透明)到 1.0(完全不透明)。 |
setWindowOpacity(float n) | 设置控件的不透明数值。 |
调整窗口透明度
(1)在界面上拖放两个按钮,分别用来增加不透明度和减少不透明度
objectName
分别为 pushButton_add 和 pushButton_sub:
(2)编写 wdiget.cpp
, 编写两个按钮的 slot 函数
- 点击
pushButton_sub
会减少不透明度,也就是窗口越来越透明 - 点击
pushButton_add
会增加不透明度,窗口会逐渐恢复
(3)执行程序
点击了几下 ‘-’ 之后,就可以透过窗⼝看到后面的内容了,点击 ‘+’ 又会逐渐恢复:
同时控制台中也可以看到 opacity 数值的变化,发现其窗口得到不透明度变化并非是精确的
注意 :
- C++ 中 float 类型遵守 IEEE 754 标准,因此在进行运算的时候会有一定的精度误差
- IEEE 754 标准 规定浮点数使用 二进制 科学计数法的方式来表示,把一个浮点数分成 符号位、有效数字、指数部分 三个部分
- 其中有效数字是用二进制表示的,比如 .1(B),表示0.5,.01(B) 表示 0.25,而 0.1 这样的小数无法用二进制精确表示出来,只能凑一个非常接近 0.1 的数
- 因此 1 - 0.1 的数值并非是 0.9
- 这里还要提一句:平时最好不要把两个浮点数直接用 == 进行比较,比如 0.1 + 0.2 == 0.3 (false)
还有个小细节,我们上面加了判定条件
- 其实不加也是可以的,超过 1.0 的数字设置不进去,因为
setWindowOpacity
内部也进行了判定
2.7 光标属性(cursor)
API | 说明 |
---|---|
cursor() | 获取当前 widget 的光标属性,返回 QCursor 对象。 |
setCursor(const QCursor& cursor) | 设置该 widget 的光标形状,仅在鼠标停留在该 widget 上时生效。 |
QGuiApplication::setOverrideCursor(const QCursor& cursor) | 设置全局光标的形状,覆盖 setCursor 设置的内容。 |
1. 在 Qt Designer 中设置按钮的光标
(1)在界面中创建一个按钮,然后直接在右侧属性编辑区修改 cursor
属性为 “打开手势”
(2)运行程序
鼠标悬停到按钮上之后,就可以看到光标的变化。
2. 通过代码设置按钮的光标
(1) 编写 widget.cpp
其中 Qt::WaitCursor
就是自带的沙漏 / 转圈形状的光标。
系统内置的光标形状如下:
Ctrl + 左键点击 Qt::WaitCursor
跳转到源码即可看到:
3. 自定义鼠标光标
Qt 自带的光标形状有限,我们也可以自己找个图片,做成鼠标的光标,比如我们这里用我们上面图标那用到的宝可梦当鼠标光标
(1)用下面说到的,创建 qrc 的方法,来创建 qrc 资源文件,添加前缀 /,并加入图片
注意: 这里 pixmap = pixmap.scaled(10, 10);
- 通过这个函数对图片进行缩放
- 注意:这里的缩放不是修改图片对象本身,而是返回一个新的图片对象副本
2.8 字体属性(QFont)
字体属性是界面设计中重要的组成部分,它们影响着文本的外观。Qt 提供了多种方式来设置和获取字体属性。
API 说明
- font():用于 获取 当前 widget 的字体信息。返回一个 QFont 对象。
- setFont(const QFont& font):用于 设置 当前 widget 的字体信息。
属性列表
属性 | 说明 |
---|---|
family | 字体家族,例如 “楷体”, “宋体”, “微软雅黑” 等 |
pointSize | 字体大小 |
weight | 字体粗细,以数值表示粗细程度,取值范围为 [0, 99],数值越大,越粗 |
bold | 是否加粗,设置为 true 相当于 weight 为 75;false 则为 50 |
italic | 是否倾斜 |
underline | 是否带有下划线 |
strikeOut | 是否带有删除线 |
1. 在 Qt Designer 中设置字体属性
1)在界面上创建一个 label
2)在右侧的属性编辑区,设置该 label 的 font 相关属性在这里调整上述属性,Qt Designer 能够对界面的属性设置支持 “实时预览”,因此我们可以实时的看到文字的变化。
3)执行程序,就可以看到上面的效果了
- 通过属性编辑这样的方式,虽然能够快速方便的修改文字相关的属性,但是还不够灵活。如果程序运行过程中需要修改文字相关属性,就需要代码操作了
2. 在代码中设置字体属性
编写 widget.cpp
,然后运行程序即可
- 在实际开发中,字体属性如何选择是一个 “审美问题”,而不是 “技术问题”,往往需要有一定的艺术细胞。
- 幸运的是,公司中 往往有专业的 “美工” / “设计” 这样的岗位,去做这方面的工作,我们程序员只要按照人家给的设计稿,把代码写出来即可,不必过多考虑怎样搭配才好看的问题。
3. Window Frame 的影响
当 widget 作为一个窗口时(例如带有标题栏等),计算尺寸和坐标有两种算法:
-
包含
window frame
的方式(如x(), y(), frameGeometry(), pos(), move()
) -
不包含
window frame
的方式(如geometry(), width(), height(), rect(), size()
)
对于非窗口的 widget,这两种计算方式的结果是一致的。
Geometry 和 FrameGeometry 的区别
(1) 在按钮的 slot 函数中编写代码 & 在构造函数中也添加同样的代码
(2)执行程序
- 可以看到:在构造函数中打印出的
geometry
和frameGeometry
是相同的。 - 但是在点击按钮时,打印的
geometry
和frameGeometry
则存在差异。
💡 原因:
-
在构造方法中,
Widget
刚刚创建出来,还没有加入到对象树中,此时也就不具备Window frame
。 -
在按钮的
slot
函数中,由于用户点击的时候,对象树已经构造好了,此时Widget
已经具备了Window frame
,因此在位置和尺寸上均出现了差异。 -
如果把上述代码修改成打印
pushButton
的geometry
和frameGeometry
,结果就是完全相同的。因为pushButton
并非是一个窗口
因此我们具体使用的时候,需要明确使用的坐标系原点究竟是谁?
4. API 设计理念
API | 说明 |
---|---|
x() | 获取横坐标。计算时包含 window frame。 |
y() | 获取纵坐标。计算时包含 window frame。 |
pos() | 返回 QPoint 对象,包含 x() 和 y() 的值及设置方法。计算时包含 window frame。 |
frameSize() | 返回 QSize 对象,包含 width() 和 height() 及其设置方法。计算时包含 window frame。 |
frameGeometry() | 返回 QRect 对象,相当于 QPoint 和 QSize 的结合体,可以获取 x, y, width, size。计算时包含 window frame 对象。 |
width() | 获取宽度。计算时不包含 window frame。 |
height() | 获取高度。计算时不包含 window frame。 |
size() | 返回 QSize 对象,包含 width() 和 height() 及其设置方法。计算时不包含 window frame。 |
rect() | 返回 QRect 对象,可以获取并设置 x, y, width, size。计算时不包含 window frame 对象。 |
geometry() | 返回 QRect 对象,可以获取 x, y, width, size。计算时不包含 window frame 对象。 |
setGeometry() | 设置窗口的位置和尺寸,可以设置 x, y, width, height 或 QRect 对象。计算时不包含 window frame 对象。 |
认真观察上面的表格,可以看到,其实这里的 API 有 frameGeometry
和 geometry
两个就足够完成所有的需求了。
为什么要提供这么多功能重复的 API 呢?
这涉及到 Qt API 的设计理念:尽量符合人的直觉。例如,Qt 的
QVector
提供了多种尾插元素的方法:
push_back
append
+=
<<
上述方法的效果都是等价的,即使不翻阅文档,单纯的凭借直觉就能把代码写对。减少了记忆负担,使编程变得更加直观和友好
5. 资源管理与路径使用
1、图片路径的选择
- 避免绝对路径:实际开发中,通常不会在代码中通过绝对路径引入图片。因为无法保证程序发布后,用户的电脑上也有同样的路径。
- 相对路径的要求:如果选择使用相对路径,则需要确保代码中的相对路径写法和图片实际所在的路径匹配。例如,代码中写作
"./image/Q&A.jpg"
,就需要在当前工作目录中创建 image 目录,并把Q&A.jpg
放进去。
2、路径类型说明
- 绝对路径:以盘符(Windows)或者以 /(Linux)开头的路径。
- 相对路径:以 .(表示当前路径)或者以 …(表示当前路径上级路径)开头的路径。其中 . 经常也会省略。使用相对路径的前提是明确“当前工作目录”。
对于 Qt 程序来说,当前工作目录可能是变化的:
- 通过 Qt Creator 运行的程序,当前工作目录是项目的构建目录
- 直接双击 exe 运行时,工作目录则是 exe 所在目录
3、构建目录的作用
所谓构建目录,是和 Qt 项目并列的,专门用来放生成的临时文件和最终 exe 的目录
Qt 使用 qrc 机制 来自动管理项目依赖的静态资源,解决了以下两个关键问题:
- 确保我们的 图片所在路径在目标用户机器上存在
- 确保我们的 图片不会被用户误删或修改
如果我们不知道这个路径在哪,可以输入下面代码来 查看运行程序的 工作目录 与 程序所在的目录
6. qrc 文件
6.1 qrc 文件的特点
-
qrc 文件是一种 XML 格式的资源配置文件
-
它用 XML 记录硬盘上的文件和对应的随意指定的资源名称,应用程序通过资源名称来访问这些资源
-
在 Qt 开发中,可以通过将资源文件添加到项目中来方便地访问和管理这些资源,这些资源文件可以位于 qrc 文件所在目录的同级或其子目录下
-
在构建程序的过程中,Qt 会把资源文件的二进制数据转成 cpp 代码,编译到 exe 中,从而使依赖的资源变得 “路径无关”。
这种资源管理机制并非 Qt 独有,很多开发框架都有类似的机制。例如 Android
的 Resources
和 AssetManager
也提供了类似的功能。
qrc 的局限性
- 不适合大文件:qrc 不适合导入太大的资源文件,因为这会导致最终 exe 文件体积增大,程序运行内存消耗增加及编译时间显著增长。
6.2 通过 qrc 管理图片作为图标
(1)右键项目,创建一个 Qt Resource File(qrc 文件), 文件名随意起(不要带中文),此处叫做 resource.qrc
如下:
(2)在 qrc 编辑器中 添加 前缀
png&pos_id=img-Sq50mLtn-1737007918100)
此处我们前缀设置成 / 即可。
所谓的前缀,可以理解成 “虚拟的目录”,这个目录在我们的电脑中并不是真实存在的,是 Qt 自己抽象出来的,它决定了后续我们如何在代码中访问资源。
(3)在资源编辑器中,点击 add Files 添加资源文件
此处我们需要添加的是:qt_bao.jpg:
注意 :
- 添加的文件必须是在 qrc 文件的同级目录或者同级目录的子目录中
- 因此我们需要把之前 D 盘中的 .jpg 复制到上述目录中。
(4)在代码中使用 qt_bao.jpg
代码中需要访问 qrc 中管理的文件时,就需要在路径上带有 : 前缀。创建的前缀叫什么名字,代码中就写什么名字:前缀 + 文件名。
注意上述路径的访问规则:
-
使用 : 作为开头,表示从 qrc 中读取资源
-
/ 是上面配置的前缀
-
qt_bao.jpg 是资源的名称
🔥 需要确保代码中编写的路径 和添加到 qrc 中资源的路径匹配,否则资源无法被访问(同时也不会有报错提示)。
运行成功后,我们可以进入到项目的构建目录中可以看到:目录中多了一个
qrc_resource.cpp
文件,直接打开这个文件可以看到:
qrc 中导入的图片资源会被转成这个 qrc_resource.cpp
(自动生成)这个 c++ 代码,代码查看如下:
上述代码其实就是通过 unsigned char
数组,把 qt_bao.jpg
中的每个字节都记录下来。
这些代码会被编译到 exe 中,后续无论 exe 被复制到哪个目录下都确保能够访问到该图片资源。
上述 qrc 这一套资源管理方案的优点和缺点都很明显:
- 优点:确保了图片、字体、剩余等资源能够真正做到 “目录无关”,无论如何都不会出现资源丢失的情况。
- 缺点:不适合管理体积大的资源。如果资源比较大(比如是几个 MB 的文件),或者资源特别多,生成的最终的 exe 体积就会比较大,程序运行消耗的内存也会增大,程序编译的时间也会显著增加。
7. 其他
7.1 ToolTip 设置
一个 GUI 程序,界面比较复杂,按钮很多,那么就需要提供一个功能:当我们鼠标悬停到这个控件的时候,就能弹出一个提示
Tooltip
是用户 悬停在 widget 上时显示的提示信息,有助于提高用户体验。
API | 说明 |
---|---|
setToolTip(const QString &tooltip) | 设置 tooltip 文本 |
setToolTipDuration(int msec) | 设置 tooltip 显示的 时间,单位为毫秒 |
设置按钮的 toolTip
(1)在界面上拖放两个按钮:objectName
设置为 pushButton_moment
和pushButton_forever
(2)编写 widget.cpp
- 观察效果,可以看到鼠标停到按钮上之后,就能弹出提示,时间到后自行消失。
7.2 Focus Policy 设置
Focus policy 决定了控件是否及如何接收 键盘焦点
设置控件获取到焦点的策略,比如某个控件 能否用鼠标选中 或者 能否通过 tab 键选中
- 所谓 “焦点”,指的就是能选中这个元素。接下来的操作(比如键盘操作),就都是针对该焦点元素进行的了。
- 比如界面上有一个输入框,此时必须要选中最高输入框,接下来的键盘按键才会输入到输入框中,如果选择别的控件或窗口,此时键盘的输入就不会到这个输入框中
- 这个对于输入框、单选框、复选框等控件非常有用的。
API | 说明 |
---|---|
focusPolicy() | 获取当前 widget 的 focus policy |
setFocusPolicy(Qt::FocusPolicy policy) | 设置 widget 的 focus policy |
Qt::FocusPolicy 是一个枚举类型,如下:
Qt::NoFocus
:控件不会接收键盘焦点。Qt::TabFocus
:控件可以通过 Tab 键接收焦点。Qt::ClickFocus
:控件在鼠标点击时接收焦点。Qt::StrongFocus
:默认值,控件可以通过 Tab 键和鼠标点击接收焦点。Qt::WheelFocus
:类似于Qt::StrongFocus
,同时控件也通过鼠标滚轮获取到焦点。
💡 代码示例:理解不同的 focusPolicy
(1)在界面上创建四个单行输入框(Line Edit)
(2)修改四个输入框的 focusPolicy 属性分别为 Qt::StrongFocus (默认取值,一般不用额外修改)、Qt::NoFucus、Qt::TabFucus、Qt::ClickFucus
结果如下:
- 此时运行程序可以看到,使用鼠标单击 / tab,就可以移动光标所在输入框,从而接下来的输入就是针对这个获取焦点的输入框展开的
- 第一个输入框 Tab / 鼠标单击都可以选中
- 第二个输入框无法输入内容
- 第三个输入框只能通过 Tab 选中
- 第四个输入框只能通过鼠标选中
GUI 中,窗口/控件的 焦点是非常主要的
比如:我们在网页做题的时候,网页时属于始终获取到焦点的状态,但是如果我们一旦切到网页/程序,则该网页立刻就能感受到失去焦点,然后从此收集我们的动作来衡量 ”作弊“
7.3 Style Sheet(QSS)
CSS(Cascading Style Sheets 层叠样式表)本身属于网页前端技术,主要用于 描述界面的样式。
- 所谓“样式”,包括但不限于大小、位置、颜色、间距、字体、背景、边框等。我们日常看到的丰富多彩的网页都会用到大量的 CSS。
- 尽管 Qt 主要用于 GUI 开发,但它与网页前端有着许多相似之处。
- 因此,Qt 引入了对 CSS 的支持,允许开发者使用类似的样式规则来定义 widgets 的外观。
然而,Qt 只能支持部分 CSS 样式属性,这些被支持的属性称为 QSS(Qt Style Sheet)。具体的支持情况可以参考 Qt 文档中的 "Qt Style Sheets Reference"
章节。
设置文本样式
(1)在界面上创建 label,然后编辑右侧的 styleSheet 属性,设置样式
或者右击,选择下面这种方式打开
然后对样式表,编写如下:
font-family: '微软雅黑';
font-size: 30px;
font-style: bond;
color: red;
- 此处的语法格式 同 CSS,使用键值对的方式设置样式。其中 键和值之间使用 : 分割;键值对之间使用 ; 分割。
- 注意:Qt Designer 只能对样式的基本格式进行校验,不能检测出哪些样式不被 Qt 支持,例如
text-align: center
这样的文本居中操作,在某些情况下可能无法支持。
编辑完成样式之后,可以看到在 Qt Designer 中能够实时预览出效果:
实现切换夜间模式
- 日间模式:文字是黑色的,背景是白色的。
- 夜间模式:文字是白色的,背景是黑色的。
(1)在界面上创建一个多行输入框(Text Edit)和两个按钮objectName
分别为 pushButton_light
和 pushButton_dark
(2)编写按钮的 slot 函数
#333
是深色,但不是完全黑色。#fff
是纯白色。#000
是纯黑色。
关于颜色,我们可以使用在线调色板或画图板工具可以查看颜色对应的数值。
关于计算机中的颜色表示
- 计算机中使用“像素”表示屏幕上的一个基本单位(即一个发光点)。每个像素都使用三个字节表示颜色,分别是 R(red)、G(green)、B(blue),每个字节取值范围是 0-255 或者 0x00-0xFF。
混合三种不同颜色的数值比例可以搭配出千千万万的颜色出来。
rgb(255, 0, 0) 或者 #FF0000 或者 #F00 表示纯红色。
rgb(0, 255, 0) 或者 #00FF00 或者 #0F0 表示纯绿色。
rgb(0, 0, 255) 或者 #0000FF 或者 #00F 表示纯蓝色。
rgb(255, 255, 255) 或者 #FFFFFF 或者 #FFF 表示纯白色。
rgb(0, 0, 0) 或者 #000000 或者 #000 表示纯黑色。
上述规则适用于一般程序的颜色设定。
实际显示器可能会有8bit 色深或者 10bit 色深等,具体情况会更加复杂。
运行程序
- 点击“日间模式”按钮,界面将显示浅色背景和深色文字。
- 点击“夜间模式”按钮,界面将显示深色背景和浅色文字。
8. 共勉
【*★,°*:.☆( ̄▽ ̄)/$:*.°★* 】那么本篇到此就结束啦,如果有不懂 和 发现问题的小伙伴可以在评论区说出来哦,同时我还会继续更新关于【QT】的内容,请持续关注我 !!