前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【QT】 控件 -- 显示类

【QT】 控件 -- 显示类

作者头像
IsLand1314
发布2025-01-27 08:22:38
发布2025-01-27 08:22:38
1000
举报
文章被收录于专栏:学习之路学习之路

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

image-20250116183518665
image-20250116183518665

(2)修改 widget.cpp,设置四个 label 的属性 ⭕

image-20250116183707404
image-20250116183707404
2、显示图片

虽然 QPushButton 也可以通过设置图标的方式设置图片,但是并非是一个好的选择,更多的时候还是希望通过 QLabel 来作为一个更单纯的显示图片的方式。

(1)在界面上创建一个 QLabel,objectName 为 label

image-20250116193035454
image-20250116193035454

(2)创建 resource.qrc 文件,并把图片导入到 qrc 中,修改 widget.cpp,给 QLabel 设置图片,给窗口(800 * 600)设置合适尺寸,修改代码,设置 scaledContents 属性,如下:

image-20250116194047516
image-20250116194047516
  • 一旦程序运行起来,QLabel 的尺寸就固定了,如果拖动窗口大小,可以看到图片并不会随着窗口大小的改变而同步变化。

为了解决这个问题,可以在 Widget 中重写 resizeEvent 函数:

image-20250116200038932
image-20250116200038932
  • 执行程序,此时改变窗口大小,图片也会随之变化:

注意:要记得把函数 在.h 文件中,声明一下

image-20250116195932188
image-20250116195932188

注意:这里的 resizeEvent 函数我们没有手动调用,但是能在窗口大小变化时被自动调用,这个过程就是依赖 C++ 中的多态来实现的。

  • Qt 框架内部管理着 QWidget 对象表示我们的窗口,在窗口大小发生改变时,Qt 就会自动调用 resizeEvent 函数
  • 但是由于实际上这个表示窗口的并非是 QWidget,而是 QWidget 的子类,也就是我们自己写的 Widget
  • 此时虽然是通过父类调用函数,但是实际上执行的是子类的函数(也就是我们重写后的 resizeEvent)
  • 获取到窗口的 event,进行 resize 处理

此处属于是多态机制的⼀种经典用法。通过上述过程就可以把自定义的代码插入到框架内部执行,相当于 “注册回调函数”

3、文本对齐、自动换行、缩进、边距

(1)创建四个 label,objectName 分别是 label 到 label_4,并且在 QFrame 中设置 frameShape 为 Box(设置边框之后看起来会更清晰一些)

img
img
image-20250116202103244
image-20250116202103244

QFrame 是 QLabel 的父类,其中 frameShape 属性用来设置边框性质:

  • QFrame::Box:矩形边框
  • QFrame::Panel:带有可点击区域的面板边框
  • QFrame::WinPanel:Windows 风格的边框
  • QFrame::HLine:水平线边框
  • QFrame::VLine:垂直线边框
  • QFrame::StyledPanel:带有可点击区域的面板边框,但样式取决于窗口主题。

(2)编写 widget.cpp,给这四个 label 设置属性,运行程序

image-20250116202923548
image-20250116202923548
  • 此处设置的文本缩进,后续的行也会产生缩进,不仅仅是首行缩进
4、设置伙伴

(1)创建两个 label 和 两个 radioButton,objectName 分别为 label、label_2、radioButton_A、radioButton_B

image-20250116203746412
image-20250116203746412

此处把 label 中的文本设置为 “快捷键 &A” 这样的形式。

  • 其中 & 后面跟着的字符就是快捷键,可以通过 alt + A 的方式来触发该快捷键。
  • 但是注意,这里的快捷键和 QPushButton 的不同 需要搭配 alt 和 单个字母的方式才能触发。
  • 绑定了伙伴关系之后,通过快捷键就可以选中对应的单选按钮 / 复选按钮。

(2)编写 widget.cpp,设置 buddy 属性【当然这里也可以使用 Qt Designer 直接设置】

image-20250116203724395
image-20250116203724395
  • 可以看到,按下快捷键 alt + a 或者 alt + b,即可选中对应的选项
3.2 LCD Number

QLCDNumer 是一个专门用来显示数字的控件,类似于 “老式计算器” 的效果。

image-20250116203917643
image-20250116203917643

属性

说明

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,objectNamelcdNumber

image-20250116210530615
image-20250116210530615

(2)修改 widget.h 代码,创建一个 QTimer 成员 和一个 handle 函数

image-20250116210827930
image-20250116210827930

(3)修改 widget.cpp,在构造函数中初始化 QTimer

  • QTimer 表示定时器,通过 start 方法启动定时器之后,就会每隔一定周期触发一次 QTimer::timeout 信号
  • 使用 connectQTimer::timeout 信号和 Widget::updateTime 连接起来,意味着每次触发 QTimer::timeout 都会执行 Widget::updateTime

handle 实现

  • 通过 intValue 获取到 QLCDNumber 内部的数值。
  • 如果 value 的值归 0 了,就停止 QTimer,接下来 QTimer 也就不会触发 timeout 信号了。
image-20250116211546619
image-20250116211546619
  • 可以看到每隔一秒钟,显示的数字就减少 1:通过 timer ms & lcd -1 实现

💡 欸,针对上面代码我们来两个操作 >

操作一:如果直接在上述 Widget 构造函数中,通过一个循环 + sleep 的方式是否可以呢?

image-20250116212048666
image-20250116212048666
  • 显然,上面这段代码是不行的,循环会使 *Widget 的构造函数无法执行完毕*,此时界面是不能正确构造和显示的。

操作二:如果直接在上述 Widget 构造函数中,另起一个线程,在新线程中完成循环 + sleep 是否可以呢?

image-20250116212404395
image-20250116212404395
  • 上面在 thread 的构造函数中传递了 一个 lambda 表达式,然后在在 lambda 表达式内部,定义了一个无限循环(while (true)),用于持续更新 QLCDNumber 的显示值。
image-20250116212542167
image-20250116212542167

这个代码同样也是不行的 “理想很美好,现实很骨感”

  • Qt 中规定:任何对于 GUI 上内容的操作必须在主线程中完成
  • 像 Widget 构造函数,以及 connect 连接的 slot 函数,都是在主线程中调用的。
  • 而我们自己创建的线程则不是,当我们自己的线程中尝试对界面元素进行修改时,Qt 程序往往会直接崩溃。

这样的约定主要是因为 GUI 中的状态往往是牵一发动全身的,修改一个地方,就需要同步的对其他内容进行调整。

  • 比如调整了某个元素的尺存,就可能影响到内部的文字位置,或者其他元素的位置。这里一连串的修改都是需要按照一定的顺序来完成的。
  • 由于多线程执行的顺序无法保障,因此 Qt 从根本上禁止了其他线程修改 GUI 状态,避免后续的一系列问题。
  • 对于 Qt 的槽函数来说,默认情况下,槽函数都是由主线程调用到,在槽函数中修改界面是没有任何问题的。

综上所述,使用定时器是实现上述功能的最合理方案。后续如果也有类似的需要 “周期性修改界面状态” 的需求也需要优先考虑使用定时器。

3.3 ProgressBar

使用 QProgress Bar 表示一个进度条

  • 注意:不要把 ProgessBar 拼写成 ProcessBar
image-20250116213513843
image-20250116213513843

属性

说明

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)在界面上创建进度条,objectNameprogressBar,其中最小值设为 0,最大值设为 100,当前值设为 0:

image-20250116213536771
image-20250116213536771

(2)修改 widget.h,创建 QTimer 和 handle 函数

image-20250116213536771
image-20250116213536771

这里有个小小的问题:虽然在 widget.h 中用到了 QTimer,但是却没在 widget.h 文件中包含 头文件,为什么这个代码编译没有出错呢?

上述问题其实是通过 Qt 内部提供的一个特殊技巧来实现的。

  • 在 Qt 中有一个专门的头文件(#include ),这个头文件中包含了 Qt 中所有类的 “前置声明”(class QWidgetclass QPushButtonclass 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

image-20250116214551637
image-20250116214551637

在实际开发中,进度条的取值往往是根据当前任务的实际进度来进行设置的

  • 比如需要读取一个很大的文件,就可以获取文件的总的大小和当前读取完毕的大小,来设置进度条的比例。
  • 由于前面我们介绍了 Qt 禁止在其他线程修改界面,因此进度条的更新往往也是需要搭配定时器来完成的。
  • 通过 定时器周期触发信号,主线程调用对应的 slot 函数,再在 slot 函数中对当前的任务进度进行计算,并更新进度条的界面效果。

【实现其他颜色进度条】

上述的进度条是用绿色表示的,但是考虑到有些人可能不喜欢绿⾊,因此我们改成一个红色的进度条。

QProgressBar 同样也是 QWidget 的子类,因此我们可以使用 styleSheet 通过样式来修改进度条的颜色。

(1)代码不变,然后去在 Qt Designer 右侧的属性编辑器中找到 QWidget 的 styleSheet 属性(之前有讲过),编辑内容:其中的 chunk 是选中进度条中的每个 “块”,使用 QProgressBar::text 则可以选中文本。

image-20250116215429395
image-20250116215429395
  • 但是我们发现当我们设置完之后,进度条中的数字会跑到左上角,因此我们还需要把 QProcessBaralignment属性设置为垂直水平居中
image-20250116215243314
image-20250116215243314

此时就可以得到同上面效果一样,但是颜色不同的进度条了,同样的,通过上述方式,也可以修改文字的颜色,字体大小等样式。

3.4 Calendar Widget

QCalendarWidget 表示⼀个 “日历”,形如:

image-20250116215740767
image-20250116215740767

核心属性

说明

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

image-20250116220455567
image-20250116220455567

(2)给 QCalendarWidget 添加 slot 函数 selectionChanged

image-20250116220711232
image-20250116220711232
  • 上面当选择不同的日期时,label 中的内容也会随之改变

3. 共勉 🔥

★,°:.☆( ̄▽ ̄)/$:.°★ 】那么本篇到此就结束啦,如果有不懂 和 发现问题的小伙伴可以在评论区说出来哦,同时我还会继续更新关于【QT】的内容,请持续关注我 !!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-01-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 前言
  • 2. 显示类控件
    • 2.1 Label
      • 1、显示不同文本
      • 2、显示图片
      • 3、文本对齐、自动换行、缩进、边距
      • 4、设置伙伴
    • 3.2 LCD Number
    • 3.3 ProgressBar
    • 3.4 Calendar Widget
  • 3. 共勉 🔥
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档