### 🔥 目录
- [@[TOC]( 🔥 目录)](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [1. 前言](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [2. 显示类控件](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [2.1 Label](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [1、显示不同文本](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [2、显示图片](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [3、文本对齐、自动换行、缩进、边距](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [4、设置伙伴](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [3.2 LCD Number](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [3.3 ProgressBar](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [3.4 Calendar Widget](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
- [3. 共勉 🔥](#🔥 目录 @[TOC]( 🔥 目录) 1. 前言 2. 显示类控件 2.1 Label 1、显示不同文本 2、显示图片 3、文本对齐、自动换行、缩进、边距 4、设置伙伴 3.2 LCD Number 3.3 ProgressBar 3.4 Calendar Widget 3. 共勉 🔥)
1. 前言
之前我在上一篇文章【QT】-- 按钮类已经说了QT 控件按钮类方面的知识以及涉及到的各种属性/函数/使用方法,现在就来开始了解显示类的相关知识啦
2. 显示类控件
2.1 Label
QLabel 可以用来显示文本和图片,核心属性如下:
属性 | 说明 |
---|---|
text | QLabel 中的文本。用于显示在标签上的文字内容。 |
textFormat | 文本的格式: - Qt::PlainText :纯文本 - Qt::RichText :富文本(支持 HTML 标签) - Qt::MarkdownText :Markdown 格式 - Qt::AutoText :根据文本内容自动决定文本格式。 |
pixmap | QLabel 内部包含的图片。用于显示静态图像。 |
scaledContents | 设置为 true 表示内容自动拉伸 填充 QLabel ;设为 false 则不会自动拉伸。 |
alignment | 对齐方式。可以设置水平和垂直方向如何对齐,例如居中、左对齐等。 |
wordWrap | 设置为 true 内部的文本会自动换行 ;设为 false 则内部文本不会自动换行。 |
indent | 设置文本缩进 。影响水平和垂直方向的缩进。具体生效的方向取决于 alignment 属性。 |
margin | 内部文本和边框之间的边距 。不同于 indent ,margin 在上下左右四个方向都同时有效。 |
openExternalLinks | 是否允许打开一个外部链接 。当 QLabel 文本内容包含 URL 时,点击链接将尝试打开浏览器访问该 URL。 |
buddy | 给 QLabel 关联一个"伙伴",点击 QLabel 时能激活对应的伙伴控件。例如,如果伙伴是一个 QCheckBox ,那么该 QCheckBox 将被选中。 |
1、显示不同文本
(1)在界面上创建四个 QLabel,尺存放大一些,objectName 分别为 label、label_2、label_3、label_4
(2)修改 widget.cpp,设置四个 label 的属性 ⭕
2、显示图片
虽然 QPushButton
也可以通过设置图标的方式设置图片,但是并非是一个好的选择,更多的时候还是希望通过 QLabel 来作为一个更单纯的显示图片的方式。
(1)在界面上创建一个 QLabel,objectName 为 label
(2)创建 resource.qrc 文件,并把图片导入到 qrc 中,修改 widget.cpp,给 QLabel 设置图片,给窗口(800 * 600)设置合适尺寸,修改代码,设置 scaledContents
属性,如下:
- 一旦程序运行起来,QLabel 的尺寸就固定了,如果拖动窗口大小,可以看到图片并不会随着窗口大小的改变而同步变化。
为了解决这个问题,可以在 Widget
中重写 resizeEvent
函数:
- 执行程序,此时改变窗口大小,图片也会随之变化:
注意:要记得把函数 在.h 文件中,声明一下
注意:这里的 resizeEvent 函数我们没有手动调用,但是能在窗口大小变化时被自动调用,这个过程就是依赖 C++ 中的多态来实现的。
- Qt 框架内部管理着 QWidget 对象表示我们的窗口,在窗口大小发生改变时,Qt 就会自动调用 resizeEvent 函数
- 但是由于实际上这个表示窗口的并非是 QWidget,而是 QWidget 的子类,也就是我们自己写的 Widget
- 此时虽然是通过父类调用函数,但是实际上执行的是子类的函数(也就是我们重写后的 resizeEvent)
- 获取到窗口的 event,进行 resize 处理
此处属于是多态机制的⼀种经典用法。通过上述过程就可以把自定义的代码插入到框架内部执行,相当于 "注册回调函数"
3、文本对齐、自动换行、缩进、边距
(1)创建四个 label,objectName 分别是 label 到 label_4,并且在 QFrame 中设置 frameShape 为 Box(设置边框之后看起来会更清晰一些)
QFrame 是 QLabel 的父类,其中 frameShape
属性用来设置边框性质:
- QFrame::Box:矩形边框
- QFrame::Panel:带有可点击区域的面板边框
- QFrame::WinPanel:Windows 风格的边框
- QFrame::HLine:水平线边框
- QFrame::VLine:垂直线边框
- QFrame::StyledPanel:带有可点击区域的面板边框,但样式取决于窗口主题。
(2)编写 widget.cpp,给这四个 label 设置属性,运行程序
- 此处设置的文本缩进,后续的行也会产生缩进,不仅仅是首行缩进
4、设置伙伴
(1)创建两个 label 和 两个 radioButton,objectName 分别为 label、label_2、radioButton_A、radioButton_B
此处把 label 中的文本设置为 "快捷键 &A" 这样的形式。
-
其中 & 后面跟着的字符就是快捷键,可以通过 alt + A 的方式来触发该快捷键。
-
但是注意,这里的快捷键和 QPushButton 的不同 需要搭配 alt 和 单个字母的方式才能触发。
-
绑定了伙伴关系之后,通过快捷键就可以选中对应的单选按钮 / 复选按钮。
(2)编写 widget.cpp,设置 buddy 属性【当然这里也可以使用 Qt Designer 直接设置】
- 可以看到,按下快捷键 alt + a 或者 alt + b,即可选中对应的选项
3.2 LCD Number
QLCDNumer
是一个专门用来显示数字的控件,类似于 "老式计算器" 的效果。
属性 | 说明 |
---|---|
intValue | QLCDNumber 显示的数字值(整数)。与 value 联动,显示整数值。 |
value | QLCDNumber 显示的数字值(浮点数)。与 intValue 联动,设置此属性时会自动四舍五入到最近的整数。 例如,给 value 设为 1.5,intValue 的值就是 2。 设置 value 和 intValue 的方法名为 display ,而不是 setValue 或 setIntValue 。 |
digitCount | 显示几位数字。设置可以显示的最大位数。 |
mode | 数字显示形式: - QLCDNumber::Dec:十进制模式,显示常规的十进制数字。 - QLCDNumber::Hex:十六进制模式,以十六进制格式显示数字。 - QLCDNumber::Bin:二进制模式,以二进制格式显示数字。 - QLCDNumber::Oct:八进制模式,以八进制格式显示数字。 只有在十进制模式下才能显示小数点后的内容。 |
segmentStyle | 设置显示风格: - QLCDNumber::Flat :平面的显示风格,数字呈现在一个平坦的表面上。 - QLCDNumber::Outline :轮廓显示风格,数字具有清晰的轮廓和阴影效果。 - QLCDNumber::Filled :填充显示风格,数字被填充颜色并与背景区分开。 |
smallDecimalPoint | 设置较小的小数点。当启用时,小数点将使用更小的段来表示,节省空间并提高显示密度。 |
【实现倒计时功能】
(1)在界面上创建⼀个 QLCDNumber
,初始值设为 10,objectName
为 lcdNumber
(2)修改 widget.h 代码,创建一个 QTimer 成员
和一个 handle 函数
(3)修改 widget.cpp,在构造函数中初始化 QTimer
-
QTimer 表示定时器,通过 start 方法启动定时器之后,就会每隔一定周期触发一次 QTimer::timeout 信号
-
使用
connect
把QTimer::timeout
信号和Widget::updateTime
连接起来,意味着每次触发 QTimer::timeout 都会执行 Widget::updateTime
handle 实现
- 通过 intValue 获取到 QLCDNumber 内部的数值。
- 如果 value 的值归 0 了,就停止 QTimer,接下来 QTimer 也就不会触发 timeout 信号了。
- 可以看到每隔一秒钟,显示的数字就减少 1:通过 timer
ms & lcd -1
实现
💡 欸,针对上面代码我们来两个操作 >
操作一:如果直接在上述 Widget 构造函数中,通过一个循环 + sleep 的方式是否可以呢?
- 显然,上面这段代码是不行的,循环会使 *Widget 的构造函数无法执行完毕*,此时界面是不能正确构造和显示的。
操作二:如果直接在上述 Widget 构造函数中,另起一个线程,在新线程中完成循环 + sleep 是否可以呢?
- 上面在 thread 的构造函数中传递了 一个 lambda 表达式,然后在在 lambda 表达式内部,定义了一个无限循环(
while (true)
),用于持续更新QLCDNumber
的显示值。
这个代码同样也是不行的
"理想很美好,现实很骨感"
- Qt 中规定:任何对于 GUI 上内容的操作必须在主线程中完成
- 像 Widget 构造函数,以及 connect 连接的 slot 函数,都是在主线程中调用的。
- 而我们自己创建的线程则不是,当我们自己的线程中尝试对界面元素进行修改时,Qt 程序往往会直接崩溃。
这样的约定主要是因为 GUI 中的状态往往是牵一发动全身的,修改一个地方,就需要同步的对其他内容进行调整。
-
比如调整了某个元素的尺存,就可能影响到内部的文字位置,或者其他元素的位置。这里一连串的修改都是需要按照一定的顺序来完成的。
-
由于多线程执行的顺序无法保障,因此 Qt 从根本上禁止了其他线程修改 GUI 状态,避免后续的一系列问题。
-
对于 Qt 的槽函数来说,默认情况下,槽函数都是由主线程调用到,在槽函数中修改界面是没有任何问题的。
综上所述,使用定时器是实现上述功能的最合理方案。后续如果也有类似的需要 "周期性修改界面状态" 的需求也需要优先考虑使用定时器。
3.3 ProgressBar
使用 QProgress Bar 表示一个进度条
- 注意:不要把
ProgessBar
拼写成ProcessBar
属性 | 说明 |
---|---|
minimum | 进度条最小值。定义进度条的起始值,默认为 0 。 |
maximum | 进度条最大值。定义进度条的结束值,默认为 100 。 |
value | 进度条当前值。表示进度条中已完成的部分,介于 minimum 和 maximum 之间。 |
alignment | 文本在进度条中的对齐方式: - Qt::AlignLeft :左对齐 - Qt::AlignRight :右对齐 - Qt::AlignCenter :居中对齐 - Qt::AlignJustify :两端对齐 |
extVisible | 进度条的数字是否可见。设置为 true 时显示进度数值,false 则隐藏。 |
orientation | 进度条的方向是水平还是垂直。 - Qt::Horizontal :水平方向 - Qt::Vertical :垂直方向 |
invertAppearance | 是否朝反方向增长进度。如果设为 true ,则进度从最大值向最小值递减。 |
textDirection | 文本的朝向。影响文本在进度条中的排列方向。 |
format | 展示的数字格式: - %p :表示进度的百分比(0-100) - %v :表示进度的数值(0-100) - %m :表示剩余时间(以毫秒为单位) - %t :表示总时间(以毫秒为单位) |
【实现进度条按时间增长功能】
(1)在界面上创建进度条,objectName
为 progressBar
,其中最小值设为 0,最大值设为 100,当前值设为 0:
(2)修改 widget.h,创建 QTimer 和 handle 函数
这里有个小小的问题:虽然在 widget.h 中用到了 QTimer,但是却没在 widget.h 文件中包含 头文件,为什么这个代码编译没有出错呢?
上述问题其实是通过 Qt 内部提供的一个特殊技巧来实现的。
-
在 Qt 中有一个专门的头文件(#include ),这个头文件中包含了 Qt 中所有类的 "前置声明"(
class QWidget
,class QPushButton
,class QTimer
)。 -
这个头文件我们一般不会直接接触到,但是包含其它的 Qt 的头文件,都会间接的包含到这个头文件。
-
如果 Widget 类的前面以及提供了 QTimer 类的声明的话,此时就可以在 Widget 中声明 QTimer 的指针 / 引用类型的成员。
-
后续如果要真正使用
QTimer
的头文件(包括创建实例,使用里面的成员),仍然要包含QTimer
的头文件(包含了QTimer
的详细的类的定义)。
那么Qt 为什么要使用上述技巧呢?上述技巧能解决什么问题?有什么提升呢?
主要解决的是编译速度的问题。
- C/C++ 代码,编译速度在其他语言横向对比中是非常慢的。
- C++ 编译速度慢和 #include 头文件有直接关系
- 由于 include 关系错综复杂,所以尽可能减少 include 头文件的个数就可以有效地减少编译时间。
- Qt 中就使用 class 前置声明的方式来尽量减少头文件的包含。通过前置声明的方式,Qt 中每个头文件包含的其它头文件数量都能得到一定的降低。
(3)修改 widget.cpp,初始化 QTimer,此处设置 100 ms 触发一次 timeout 信号,也就是 ⼀秒钟触发 10 次,并且实现 handle
在实际开发中,进度条的取值往往是根据当前任务的实际进度来进行设置的
-
比如需要读取一个很大的文件,就可以获取文件的总的大小和当前读取完毕的大小,来设置进度条的比例。
-
由于前面我们介绍了 Qt 禁止在其他线程修改界面,因此进度条的更新往往也是需要搭配定时器来完成的。
-
通过 定时器周期触发信号,主线程调用对应的 slot 函数,再在 slot 函数中对当前的任务进度进行计算,并更新进度条的界面效果。
【实现其他颜色进度条】
上述的进度条是用绿色表示的,但是考虑到有些人可能不喜欢绿⾊,因此我们改成一个红色的进度条。
QProgressBar 同样也是 QWidget 的子类,因此我们可以使用 styleSheet 通过样式来修改进度条的颜色。
(1)代码不变,然后去在 Qt Designer 右侧的属性编辑器中找到 QWidget 的 styleSheet 属性(之前有讲过),编辑内容:其中的 chunk
是选中进度条中的每个 "块",使用 QProgressBar::text
则可以选中文本。
- 但是我们发现当我们设置完之后,进度条中的数字会跑到左上角,因此我们还需要把
QProcessBar
的alignment
属性设置为垂直水平居中
此时就可以得到同上面效果一样,但是颜色不同的进度条了,同样的,通过上述方式,也可以修改文字的颜色,字体大小等样式。
3.4 Calendar Widget
QCalendarWidget
表示⼀个 "日历",形如:
核心属性 | 说明 |
---|---|
selectDate | 当前选中的日期。 |
minimumDate | 最小日期,定义用户可以选择的最早日期。 |
maximumDate | 最大日期,定义用户可以选择的最晚日期。 |
firstDayOfWeek | 每周的第一天(也就是日历的第一列)是周几。 |
gridVisible | 是否显示表格的边框,默认为 true 显示边框。 |
selectionMode | 是否允许选择日期。可以设置为单选或不选。 |
navigationBarVisible | 日历上方标题是否显示,默认为 true 显示导航栏。 |
horizontalHeaderFormat | 日历上方标题显示的日期格式,控制顶部标题栏的内容。 |
verticalHeaderFormat | 日历第一列显示的内容格式,控制左侧垂直标题栏的内容。 |
dateEditEnabled | 是否允许日期被编辑,默认为 false 不可编辑。 |
重要信号 | 说明 |
---|---|
selectionChanged(const QDate&) | 当选中的日期发生改变时发出。参数是一个 QDate 类型,保存了新的选中日期。 |
activated(const QDate&) | 当双击一个有效的日期或者按下回车键时发出。参数是一个 QDate 类型,保存了选中的日期。 |
currentPageChanged(int, int) | 当年份月份改变时发出。参数表示改变后的新年份和月份,分别为 int 类型。 |
【获取选中的日期】
(1)在界面上创建一个 QCalendarWidget 和一个 label,objectName 分别为 calendarWidget,label
(2)给 QCalendarWidget 添加 slot 函数 selectionChanged
- 上面当选择不同的日期时,label 中的内容也会随之改变
3. 共勉 🔥
【★,° :.☆( ̄▽ ̄)/$:.°★ 】那么本篇到此就结束啦,如果有不懂 和 发现问题的小伙伴可以在评论区说出来哦,同时我还会继续更新关于【QT】的内容,请持续关注我 !!