【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件
🔥 目录
- 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】的内容,请持续关注我 !!
相关文章:
【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件
🔥 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用(Enabled) 2.3 坐标系(Geometry) **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题(windowTiltle&a…...
Spring WebFlux
文章目录 一、概述1、Spring体系定位2、Spring MVC和WebFlux差异 二、入门1、依赖2、ReactorHttpHandlerAdapter(main启动)3、DispatcherHandler(SpringWebFlux启动)4、WebFilter 三、DispatcherHandler理解1、handle 前置知识&am…...
【AI | pytorch】torch.polar的使用
一、torch.polar的使用 torch.polar 是 PyTorch 中用来生成复数张量的一个函数,但它与数学中的复数表达式 ( z re^{i\theta} ) 是等价的。 具体来说,torch.polar(abs, angle) 接受两个实数张量参数: abs:表示复数的模长&#…...
AWTK fscript 中的 输入/出流 扩展函数
fscript 是 AWTK 内置的脚本引擎,开发者可以在 UI XML 文件中直接嵌入 fscript 脚本,提高开发效率。本文介绍一下 fscript 中的 iostream 扩展函数 1.iostream_get_istream 获取输入流对象。 原型 iostream_get_istream(iostream) > object示例 va…...
【多线程】线程池
一、什么是线程池 线程池(Thread Pool)是一种多线程并发执行的设计模式,它通过维护一个线程集合来执行多个任务,避免频繁地创建和销毁线程,提高系统性能和响应速度。 就好比如你经营了一家餐饮店,你名下有…...
小结:路由器配置和管理 RIP协议
华为路由器中配置和管理 RIP(Routing Information Protocol)的相关指令主要分为以下几个部分:基础配置指令、接口配置指令、路由控制指令和调试指令。以下是总结: 1. 启用 RIP 协议 [Huawei] rip 1rip 1:表示创建并启…...
基于海思soc的智能产品开发(高、中、低soc、以及和fpga的搭配)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 市场上关于图像、音频的soc其实非常多,这里面有高、中、低档,开发方式也不相同。之所以会这样,有价格的因素&am…...
于灵动的变量变幻间:函数与计算逻辑的浪漫交织(下)
大家好啊,我是小象٩(๑ω๑)۶ 我的博客:Xiao Xiangζั͡ޓއއ 很高兴见到大家,希望能够和大家一起交流学习,共同进步。 这一节我们主要来学习单个函数的声明与定义,static和extern… 这里写目录标题 一、单个函数…...
偷偷的学Java
序章:为何要偷偷学Java? • Java,不仅仅是一种编程语言 • 偷偷学Java,快速提升你的竞争力 •Java学习秘籍 第一章:Java的神秘面纱 •Java的起源与发展历程 •Java的生态系统与应用场景 • Java与其他编程语言的…...
以单用户模式启动 Linux 的方法
注:本文为 “Linux 启动单用户模式” 相关文章合辑。 未整理去重。 以单用户模式启动 linux 的三种方法 作者: Magesh Maruthamuthu 译者: LCTT Xiaobin.Liu 2020-05-03 23:01 单用户模式,也被称为维护模式,超级用户…...
【AI论文】生成式视频模型是否通过观看视频学习物理原理?
摘要:AI视频生成领域正经历一场革命,其质量和真实感在迅速提升。这些进步引发了一场激烈的科学辩论:视频模型是否学习了能够发现物理定律的“世界模型”,或者,它们仅仅是复杂的像素预测器,能够在不理解现实…...
【有啥问啥】Contrastive Captioners(CoCa):对比式图像描述模型——图像-文本基础模型的新范式
Contrastive Captioners(CoCa):对比式图像描述模型——图像-文本基础模型的新范式 引言 随着深度学习技术的发展,多模态模型在处理视觉和语言任务方面的能力逐渐增强。特别是大规模预训练模型的兴起,使得这些模型可以快速迁移到许多下游任务…...
Python(十七)excel指定列自动翻译成英文
前言 本章主要讲述在excel的指定列后面添加一列,并翻译成英文 一、效果图 二、代码 实际需求: # -*- codeing utf-8 -*- # time: 2025/1/16 16:32 # Author : Mikasa # # Aim:自动将客户发的货物清单里的商品名称,翻译成英文…...
【论文投稿】探秘计算机视觉算法:开启智能视觉新时代
目录 引言 一、计算机视觉算法基石:图像基础与预处理 二、特征提取:视觉信息的精华萃取 三、目标检测:从图像中精准定位目标 四、图像分类:识别图像所属类别 五、语义分割:理解图像的像素级语义 六、计算机视觉…...
【机器学习实战入门】使用LSTM机器学习预测股票价格
机器学习在股票价格预测中有重要的应用。在这个机器学习项目中,我们将讨论如何预测股票的收益。这是一个非常复杂的任务,充满了不确定性。我们将会把这个项目分成两部分进行开发: 首先,我们将学习如何使用 LSTM 神经网络预测股票…...
(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)
一、四大坐标系介绍 1,世界坐标系 从这个世界(world)的视角来看物体 世界坐标系是3D空间坐标,每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)表示 2,相机坐标系 相机本身具有一个坐标系&…...
Bootstrap 下拉菜单
Bootstrap 下拉菜单 Bootstrap 是一个流行的前端框架,它提供了许多预构建的组件,其中之一就是下拉菜单。下拉菜单是一个交互式元素,允许用户从一系列选项中选择一个。在本篇文章中,我们将详细介绍如何在 Bootstrap 中创建和使用下…...
WinHttp API接口辅助类实现GET POST网络通讯
1、简述 近期需要在MFC基础上开发网络Http通讯,开始使用的WinINet进行通讯,后面发现WinINet对连接超时这块不支持设置,在网上搜索了几种方式效果都不太好,于是决定用WinHttp API接口进行通讯,分别对GET、POST进行了封装。 2、使用到接口 2.1、WinHttpOpen WinHttpOpen 是…...
Elasticsearch实战应用
嘿,小伙伴们,今天咱们来唠唠Elasticsearch,这可是个超厉害的搜索引擎,能帮你在海量数据里快速找到想要的东西,就像给你的数据装上了“放大镜”。 一、啥是Elasticsearch 简单来说,Elasticsearch就是一个基…...
MySQL存储过程
存储过程: 事先经过编译并存储在数据库中的一段sql语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的,思想上就是sql语言层面的代码封装与重用 …...
安路FPGA开发工具TD:问题解决办法 及 Tips 总结
安路科技(Anlogic)是一家专注于高性能、低功耗可编程逻辑器件(FPGA)设计和生产的公司。其提供的开发工具TD(TangDynasty)是专门为安路FPGA系列产品设计的集成开发环境(IDE)。以下是对…...
高精度阶乘C++实现
高精度计算,实际上就是模拟竖式计算,代码如下,请慢慢消化,如有不足或建议,请在评论区留言 这个阶乘操作实际上就是高精度乘法的运用,可以非常容易的在考场上写出来 #include <bits/stdc.h> using na…...
PageHelper快速使用
依赖 <!--分页插件PageHelper--> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.7</version> </dependency>示例 /** * 封装分页结果…...
“AI 辅助决策系统:决策路上的智慧领航员
在当今瞬息万变的时代,无论是企业的运营管理,还是个人在生活中的重大抉择,都需要精准、高效的决策。然而,信息的繁杂和未来的不确定性,常常让决策变得困难重重。这时,AI 辅助决策系统宛如一位智慧的领航员&…...
[Linux] linux 系统中如何添加自动启动程序
背景:在嵌入式系统中,需要开机自动启动所编写的程序【可执行文件】。 解决方法:原理就是Linux开机会自动执行一些文件。在/etc/profile中添加执行程序的脚本。/etc/profile 是一个系统级的配置文件,在用户登录Linux系统时自动执行…...
Linux之网络套接字
Linux之网络套接字 一.IP地址和端口号二.TCP和UDP协议2.1网络字节序 三.socket编程的常见API四.模拟实现UDP服务器和客户端五.模拟实现TCP服务器和客户端 一.IP地址和端口号 在了解了网络相关的基础知识之后我们知道了数据在计算机中传输的流程并且发现IP地址在其中占据了确定…...
LeetCode 2266.统计打字方案数:排列组合
【LetMeFly】2266.统计打字方案数:排列组合 力扣题目链接:https://leetcode.cn/problems/count-number-of-texts/ Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。 为了 打出 一个字母,Alice 需要 按 对应字母 i 次,…...
Jmeter 动态参数压力测试时间段预定接口
🎯 本文档详细介绍了如何使用Apache JMeter进行压力测试,以评估预定接口在高并发场景下的性能表现。通过创建线程组模拟不同数量的用户并发请求,利用CSV文件动态配置时间段ID和用户token,确保了测试数据的真实性和有效性。文档中还…...
Learning Prompt
说明:这是我的学习笔记,很多内容转自网络,请查阅文章末尾的参考资料。 目录 基本要求(C.R.E.A.T.E)总结文章(Summarise)改写文章(Rewrite)根据参考资料回答问题(Question & Answer)参考资料 基本要求(C.R.E.A.T.E) Character This is th…...
微信消息群发(定时群发)-UI自动化产品(基于.Net平台+C#)
整理 | 小耕家的喵大仙 出品 | CSDN(ID:lichao19897314) 关联源码及工具下载https://download.csdn.net/download/lichao19897314/90096681https://download.csdn.net/download/lichao19897314/90096681https://download.csdn.net/download/…...
华为HuaweiCloudStack(一)介绍与架构
本文简单介绍了华为HCS私有云解决方案,并从下至上介绍HCS的整体架构,部署架构、部署方式等内容。 目录 HCS简介 HCS架构 纵向结构 ?管理平台类型 HCS节点类型 FusionSphere OpenStack CPS ServiceOM SC 运营面 OC 运维面 HCS部署架构 regi…...
【博客之星】2024年度个人成长、强化学习算法领域总结
📢在2025年初,非常荣幸能通过审核进入到《2024年度CSDN博客之星总评选》TOP300的年度评选中,排名40。这还是第一次来到这个阶段,作为一名博士研究生,还是备受鼓舞的。在这里我将以回顾的方式讲述一下这一年在CSDN中走过…...
Git 分支策略
文章目录 1. Git Flow2. GitHub Flow3. GitLab Flow4. Trunk-Based Development5. Release Flow分支最佳实践 Git 分支策略是组织和管理工作特性开发、协作和版本控制的技术。选择合适的策略取决于团队规模、项目需求和部署需求。以下是常见的 Git 分支策略: 1. Git…...
《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统
和组合导航一样,也可以通过预积分 IMU 因子加上雷达残差来实现基于预积分和图优化的紧耦合 LIO 系统。一些现代的 Lidar SLAM 系统也采用了这种方式。相比滤波器方法来说,预积分因子可以更方便地整合到现有的优化框架中,从开发到实现都更为便…...
Mysql学习笔记
连接数据库 找到 MySQL 安装目录下的 bin 目录,然后打开命令窗口,在命令窗口中按如下语法输入命令: mysql - h MySQL 数据库服务器的 IP 地址 - u 用户名 - p 然后按下回车键,输入密码即可 数据库操作 创建数据库 CREAT…...
Safari常用快捷键
一、书签边栏 1、显示或隐藏书签边栏:Control-Command-1 2、选择下一个书签或文件夹:向上头键或向下头键 3、打开所选书签:空格键 4、打开所选文件夹:空格键或右箭头键 5、关闭所选文件夹:空格键或左箭头键 6、更…...
OpenEuler学习笔记(二):用通俗的道理讲操作系统原理
用通俗的道理讲操作系统原理 基础概念类比 把OpenEuler操作系统想象成一个大型的工厂,这个工厂有各种各样的部门,每个部门都有自己的职责,共同协作来让整个工厂正常运转。内核就像是工厂的管理中心,它负责指挥和协调所有的工作。 …...
ros2-7.5 做一个自动巡检机器人
7.5.1 需求及设计 又到了小鱼老师带着做最佳实践项目了。需求:做一个在各个房间不断巡逻并记录图像的机器人。 到达目标点后首先通过语音播放到达目标点信息, 再通过摄像头拍摄一张图片保存到本地。 7.5.2 编写巡检控制节点 在chapt7_ws/src下新建功…...
使用 `scanpy` 观察 `AnnData` 对象内部数据结构
以下是使用 scanpy 观察 AnnData 对象内部数据结构的步骤: 一、导入必要的库: import scanpy as sc二、读取 AnnData 对象: 假设你的 AnnData 对象存储在一个文件中,例如 adata.h5ad,你可以使用以下代码读取它: adata = sc.read(adata.h5ad)如果你已经有了 adata 对象…...
《CPython Internals》阅读笔记:p232-p249
《CPython Internals》学习第 13天,p232-p249 总结,总计 18 页。 一、技术总结 无。 二、英语总结(生词:1) 1.overhead (1)overhead: over-(“above”) head(“top part, uppermost section”) overhead的字面意思是:above…...
Java并发08 - 并发安全容器详解
并发容器详解 文章目录 并发容器详解一:不使用并发容器如何保证安全二:阻塞队列容器2:ArrayBlockingQueue2.1:内部成员2.2:put方法的实现2.3:take方法的实现 3:LinkedBlockingQueue3.1ÿ…...
抽奖系统(3——奖品模块)
1. 图片上传 application.properties 配置上传文件路径 ## 文件上传 ## # 目标路径 pic.local-pathD:/PIC # spring boot3 升级配置名 spring.web.resources.static-locationsclasspath:/static/,file:${pic.local-path} tip: 1. 如果访问的是本地路径,…...
36.centos7上安装python3.6.5、安装卸载依赖包
查看openssl的版本号,默认python3.6.5需要OpenSSL 1.0.2以上的版本支持。 监测安装好的python,是否可以正确导入ssl和_ssl包 pip3安装依赖包 通过Pycharm工具导出requirements.txt文件 查看/usr/bin/目录下的软连接 pip3, python...
微透镜阵列精准全检,白光干涉3D自动量测方案提效70%
广泛应用的微透镜阵列 微透镜是一种常见的微光学元件,通过设计微透镜,可对入射光进行扩散、光束整形、光线均分、光学聚焦、集成成像等调制,进而实现许多传统光学元器件难以实现的特殊功能。 微透镜阵列(Microlens Array&#x…...
nature genetics | scATAC-seq预测scRNA-seq,识别影响基因表达的新染色质区域
–https://doi.org/10.1038/s41588-024-01689-8 Single-cell multi-ome regression models identify functional and disease-associated enhancers and enable chromatin potential analysis 研究团队和单位 Christina S. Leslie–Memorial Sloan Kettering Cancer Center …...
简述mysql 主从复制原理及其工作过程,配置一主两从并验证。
MySQL 主从同步是一种数据库复制技术,它通过将主服务器上的数据更改复制到一个或多个从服务器,实现数据的自动同步。 主从同步的核心原理是将主服务器上的二进制日志复制到从服务器,并在从服务器上执行这些日志中的操作。 MySQL主从同步是基…...
Java API:封装自定义响应类
本文介绍 Web 服务开发中自定义响应,涵盖标准 HTTP 响应状态码局限性、自定义响应价值、设计原则与实现、在 Spring Boot 项目应用、与其他响应格式对比总结及应用场景。 1. 标准HTTP响应与自定义响应 1.1标准HTTP响应状态码 在 Web 服务开发中,HTTP…...
【Unity3D】利用Hinge Joint 2D组件制作绳索效果
目录 一、动态绳索 (可移动根节点) 二、静态绳索 三、利用Skinning Editor(Unity2022.3.15f1正常使用) 四、注意事项 一、动态绳索 (可移动根节点) 动态绳索 DynamicRope空物体 Anchor和whitecircle是相同位置的物体ÿ…...
vim练级攻略(精简版)
vim推荐配置: curl -sLf https://gitee.com/HGtz2222/VimForCpp/raw/master/install.sh -o ./install.sh && bash ./install.sh 0. 规定 Ctrl-λ 等价于 <C-λ> :command 等价于 :command <回车> n 等价于 数字 blank字符 等价于 空格,tab&am…...
嵌入式硬件篇---PID控制
文章目录 前言第一部分:连续PID1.比例(Proportional,P)控制2.积分(Integral,I)控制3.微分(Derivative,D)控制4.PID的工作原理5..实质6.分析7.各种PID控制器P控…...