【Qt】常用控件(上)

🌈个人主页: 秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343
🔥 系列专栏: https://blog.csdn.net/qinjh_/category_13030435.html

目录

控件概述

[QWidget 核心属性](#QWidget 核心属性)

核心属性概览

enabled

geometry

[window frame 的影响](#window frame 的影响)

windowTitle

windowIcon

windowOpacity

cursor

font

toolTip

focusPolicy

styleSheet

按钮类控件

[Push Button](#Push Button)

[Radio Buttion](#Radio Buttion)

[Check Box](#Check Box)

[Tool Button](#Tool Button)

显示类控件

Label

[LCD Number](#LCD Number)

ProgressBar

[Calendar Widget](#Calendar Widget)


前言

💬 hello! 各位铁子们大家好哇。

今日更新了常用控件的内容

🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

控件概述

Widget 是 Qt 中的核心概念. 英文原义是 "小部件", 我们此处也把它翻译为 "控件" .

控件是构成一个图形化界面的基本要素.

Qt 作为一个成熟的 GUI 开发框架, 内置了大量的常用控件. 这一点在 Qt Designer 中就可以看到端倪. 并且 Qt 也提供了 "自定义控件" 的能力, 可以让程序猿在现有控件不能满足需求的时候, 对现有控件做 出扩展, 或者手搓出新的控件.

QWidget 核心属性

在 Qt 中, 使用 QWidget 类表示 "控件". 像按钮, 视图, 输入框, 滚动条等具体的控件类, 都是继承自 QWidget.

可以说, QWidget 中就包含了 Qt 整个控件体系中, 通用的部分

在 Qt Designer 中, 随便拖一个控件过来, 选中该控件, 即可在右下方看到 QWidget 中的属性

这些属性既可以通过 QtDesigner 会直接修改, 也可以通过代码的方式修改.

这些属性的具体含义, 在 Qt Assistant 中均有详细介绍.

在 Qt Assistant 中搜索 QWidget, 即可找到对应的文档说明. (或者在 Qt Creator 代码中, 选中 QWidget, 按 F1 也可).

核心属性概览

下列表格列出了 QWidget 中的属性及其作用.

enabled

  • 所谓 "禁用" 指的是该控件不能接收任何用户的输入事件, 并且外观上往往是灰色的.
  • 如果一个 widget 被禁用, 则该 widget 的子元素也被禁用.

代码示例: 使用代码创建一个禁用状态的按钮

运行程序, 可以看到按钮处于灰色状态, 无法被点击.

代码示例: 通过按钮2 切换按钮1 的禁用状态

使用 Qt Designer 拖两个按钮到 Widget 中

两个按钮的 objectName 分别设置为 pushButton 和 pushButton_enable

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 这样的代码获取到界面上的 widget 对象了.

运行程序, 可以看到, 初始情况下, 上面的按钮是可用状态

点击下方按钮, 即可使上方按钮被禁用; 再次点击下方按钮, 上方按钮就会解除禁用. (禁用状态的按钮为 灰色, 且不可点击)

geometry

位置和尺寸. 其实是四个属性的统称:

  • x 横坐标
  • y 纵坐标
  • width 宽度
  • height 高度

但是实际开发中, 我们并不会直接使用这几个属性, 而是通过一系列封装的方法来获取/修改.

对于 Qt 的坐标系, 不要忘记是一个 "左手坐标系". 其中坐标系的原点是当前元素的父元素的左上角.

代码示例: 控制按钮的位置

在界面中拖五个按钮

五个按钮的 objectName 分别为 pushButton_target , pushButton_up , pushButton_down , pushButton_left , pushButton_right 五个按钮的初始位置和大小都随意.

在 widget.cpp 中编写四个按钮的 slot 函数

运行程序, 可以看到, 按下下方的四个按钮, 就会控制 target 的左上角的位置. 对应的按钮整个尺寸也会 发生改变.

起始图形:

我们一直点击down后形状如下:

上述代码中我们是直接设置的 QRect 中的 x, y . 实际上 QRect 内部是存储了左上和右下两个点的坐 标, 再通过这两个点的坐标差值计算长宽.

单纯修改左上坐标就会引起整个矩形的长宽发生改变.

如果想让整个按钮都移动, 可以改成下列代码:

使用setGeometry的第二个版本。前两个参数表示左上角坐标,后两个参数表示长和宽。

长和宽不变,修改坐标即可实现整个按钮移动。

代码示例: 一个表白程序

往界面上拖拽两个按钮和一个 Label

Pushbutton 的 objectName 为 pushButton_accept 和 pushButton_reject , label 的 objectName 为 label

控件中文本如下图所示.

在 widget.cpp 中添加 slot 函数

运行程序, 可以看到, 当点击 "拒绝" 时, 按钮就跑了.

window frame 的影响

如果 widget 作为一个窗口 (带有标题栏, 最小化, 最大化, 关闭按钮), 那么在计算尺寸和坐标的 时候就有两种算法. 包含 window frame 和 不包含 window frame.

其中 x(), y(), frameGeometry(), pos(), move() 都是按照包含 window frame 的方式来计算 的.

其中 geometry(), width(), height(), rect(), size() 则是按照不包含 window frame 的方式来计 算的.

当然, 如果一个不是作为窗口的 widget , 上述两类方式得到的结果是一致的.

相关 API

代码示例: 感受 geometry 和 frameGeometry 的区别.

运行后发现两个的结果是一样的。

修改代码:

运行后,可以看到, 构造函数中, 打印出的 geometry 和 frameGeometry 是相同的.

但是在点击按钮时, 打印的 geometry 和 frameGeometry 则存在差异.
注意:

在构造方法中, Widget 刚刚创建出来, 还没有加入到对象树中. 此时也就不具备 Window frame.

在按钮的 slot 函数中, 由于用户点击的时候, 对象树已经构造好了, 此时 Widget 已经具备了 Window frame, 因此在位置和尺寸上均出现了差异

windowTitle

注意! 上述设置操作针对不同的 widget 可能会有不同的行为.

如果是顶层 widget (独立窗口), 这个操作才会有效.

如果是子 widget, 这个操作无任何效果.

代码示例:

上面运行结果可以知道,不是顶层的widget并不会生效,也不会报错。

windowIcon

同 windowTitle, 上述操作仅针对顶层 widget 有效.

代码示例: 设置窗口图标

之前推荐用堆来创建对象,主要是因为要确保当前的控件的生命周期是足够的,要通过Qt对象树来释放对象。QIcon自身是一个比较小的对象,它本身释放不释放,不影响图标的最终显示,它也不支持对象树。所以在栈上创建。

注意:

Windows 下路径的分隔符可以使用 / 也可以使用 \ . 但是如果在 字符串 中使用 \ , 需要写 作转义字符的形式 \\ . 因此我们还是更推荐使用 / .
实际开发中, 我们一般不会在代码中通过绝对路径引入图片. 因为我们无法保证程序发布后, 用 户的电脑上也有同样的路径

如果使用相对路径, 则需要确保代码中的相对路径写法和图片实际所在的路径匹配 (比如代码 中写作 "./image/rose.jpg", 就需要在当前工作目录中创建 image 目录, 并把 rose.jpg 放进 去).
绝对路径: 以盘符(windows)或者以 / (Linux) 开头的路径

相对路径: 以 . (表示当前路径) 或者 以 .. (表示当前路径上级路径) 开头的路径. 其中 . 经常也 会省略. 相对路径的前提是需要明确 "当前工作目录".

对于 Qt 程序来说, 当前工作目录可能是变化的. 比如通过 Qt Creator 运行的程序, 当前工作目录是项目 的构建目录; 直接双击 exe 运行, 工作目录则是 exe 所在目录.

所谓构建目录, 是和 Qt 项目并列的, 专门用来放生成的临时文件和最终 exe 的目录

Qt中还有一种机制,叫qrc机制。

给Qt项目引入一个额外的xml文件(后缀名用.qrc表示),在这个xml中把要使用的文件资源给导入进来,并且在xml中进行记录。

Qt在编译项目的时候,就会根据qrc中描述的图片信息,找到图片内容,并且提取出图片的二进制数据,把这些二进制数据转成c++代码,最终编译到.exe里。

代码示例: 通过 qrc 管理图片作为图标

右键项目, 创建一个 Qt Resource File (qrc 文件), 文件名随意起(不要带中文), 此处叫做 resource.qrc .(不加后缀的话,他也会自动带上)

在 qrc 编辑器中, 添加前缀.

此处我们前缀设置成 / 即可.

所谓的前缀, 可以理解成 "目录" . 这个前缀决定了后续我们如何在代码中访问资源

在 资源编辑器 中, 点击 add Files 添加资源文件. 此处我们需要添加的是 cat.jpg

导入图片的时候,需要确保你的图片必须在resource.qrc文件的同级目录或者同级目录的子目录里。

上面的问题,只需要把图片拷贝到当前项目目录中即可。

添加完毕后, 可以在 资源编辑器 中看到添加好的文件

在代码中使用 rose.jpg

注意上述路径的访问规则.

  • 使用 : 作为开头, 表示从 qrc 中读取资源.
  • / 是上面配置的前缀
  • cat.jpg 是资源的名称

需要确保代码中编写的路径和添加到 qrc 中资源的路径匹配. 否则资源无法被访问 (同时也不会有报错 提示).

接下来, 我们可以进入到项目的构建目录, 可以看到, 目录中多了一个 qrc_resource.cpp 文件. 直 接打开这个文件, 可以看到类似如下代码:

qrc中导入的图片资源,就会被转成这个qrc_resource.cpp文件。

上述代码其实就是通过 unsigned char 数组, 把 cat.jpg 中的每个字节都记录下来. 这些代码会被编译 到 exe 中. 后续无论 exe 被复制到哪个目录下, 都确保能够访问到该图片资源.

windowOpacity

代码示例: 调整窗口透明度

在界面上拖放两个按钮, 分别用来增加不透明度和减少不透明度. objectName 分别为 pushButton_add 和 pushButton_sub

编写 wdiget.cpp, 编写两个按钮的 slot 函数

  • 点击 pushButton_sub 会减少不透明度, 也就是窗口越来越透明.
  • 点击 pushButton_add 会增加不透明度, 窗口会逐渐恢复.

控制台中也可以看到 opacity 数值的变化

注意, C++ 中 float 类型遵守 IEEE 754 标准, 因此在进行运算的时候会有一定的精度误差. 因此 1 - 0.1 的数值并非是 0.9 .

cursor

代码示例: 在 Qt Designer 中设置按钮的光标

在界面中创建一个按钮

直接在右侧属性编辑区修改 cursor 属性为 "等待"

运行程序, 鼠标悬停到按钮上, 即可看到光标的变化

代码示例: 通过代码设置按钮的光标

其中 Qt::WaitCursor 就是自带的等待形状的光标.

系统内置的光标形状如下:

Ctrl + 左键 点击 Qt::WaitCursor 跳转到源码即可看到.

代码示例: 自定义鼠标光标

Qt 自带的光标形状有限. 我们也可以自己找个图片, 做成鼠标的光标.

创建 qrc 资源文件, 添加前缀 / , 并加入cat.png

编写 widget.cpp

运行程序, 观察效果即可。

QPixmap通过这个对象就可以表示一个图片

缩放不是修改图片本身,而是返回一个新的图片的副本。

font

关于 QFont

代码示例: 在 Qt Designer 中设置字体属性

在界面上创建一个 label

在右侧的属性编辑区, 设置该 label 的 font 相关属性

在这里调整上述属性, 可以实时的看到文字的变化.

执行程序, 观察效果

代码示例: 在代码中设置字体属性

toolTip

toolTip 只是给用户看的. 在代码中一般不需要获取到 toolTip.

代码示例: 设置按钮的 toolTip

在界面上拖放两个按钮. objectName 设置为 pushButton_yes 和 pushButton_no

编写 widget.cpp并运行程序, 观察效果

可以看到鼠标停到按钮上之后, 就能弹出提示. 时间到后自行消失.

focusPolicy

设置控件获取到焦点的策略. 比如某个控件能否用鼠标选中或者能否通过 tab 键选中.

所谓 "焦点" , 指的就是能选中这个元素. 接下来的操作 (比如键盘操作), 就都是针对该焦点元素进行的 了. 这个对于 输入框, 单选框, 复选框等控件非常有用的.

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 (Cascading Style Sheets 层叠样式表) 本身属于网页前端技术. 主要就是用来描述界面的 样式

所谓 "样式", 包括不限于 大小, 位置, 颜色, 间距, 字体, 背景, 边框等.

我们平时看到的丰富多彩的网页, 就都会用到大量的 CSS.

Qt 虽然是做 GUI 开发, 但实际上和 网页前端 有很多异曲同工之处. 因此 Qt 也引入了对于 CSS 的支持.

CSS 中可以设置的样式属性非常多. 基于这些属性 Qt 只能支持其中一部分, 称为 QSS (Qt Style Sheet)

代码示例: 设置文本样式

在界面上创建 label

编辑右侧的 styleSheet 属性, 设置样式;也可以右键找到"改变样式表"

此处的语法格式同 CSS, 使用键值对的方式设置样式. 其中键和值之间使用 : 分割. 键值对之间使用 ; 分割.

编辑完成样式之后, 可以看到在 Qt Designer 中能够实时预览出效果.

代码示例: 实现切换夜间模式.

在界面上创建一个多行输入框 (Text Edit) 和两个按钮objectName 分别为 pushButton_light 和 pushButton_dark

编写按钮的 slot 函数

关于计算机中的颜色表示:

计算机中使用 "像素" 表示屏幕上的一个基本单位(也就是一个发亮的光点).

每个光点都使用三个字节表示颜色, 分别是 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 表示纯黑色.

qq自带的截图中,就有取色器,我们可以根据这个数值来设置想要的颜色。

初始情况下,Widget的背景色不是纯白的,而是有点灰的,需要我们进行数值的设置

运行程序, 点击 "日间模式", 就是浅色背景, 深色文字; 点击 "夜间模式", 就是深色背景, 浅色文字.

按钮类控件

Push Button

使用 QPushButton 表示一个按钮. 这也是当前我们最熟悉的一个控件了

QPushButton 继承自 QAbstractButton . 这个类是一个抽象类. 是其他按钮的父类.

在 Qt Designer 中也能够看到这里的继承关系

QAbstractButton 中, 和 QPushButton 相关性较大的属性

  1. QAbstractButton 作为 QWidget 的子类, 当然也继承了 QWidget 的属性. 上面 介绍的 QWidget 里的各种属性用法, 对于 QAbstractButton 同样适用. 因此表格仅 列出 QAbstractButton 独有的属性.
  2. Qt 的 api 设计风格是非常清晰的. 此处列出的属性都是可以 获取 和 设置 的. 例如, 使 用 text() 获取按钮文本; 使用 setText() 设置文本.

事实上, QPushButton 的核心功能都是 QAbstractButton 提供的. 自身提供的属性都比较简 单.

其中 default 和 audoDefault 影响的是按下 enter 时自动点击哪个按钮的行为; flat 把按钮 设置为扁平的样式. 这里我们暂时都不做过多关注

代码示例: 带有图标的按钮

创建 resource.qrc 文件, 并导入图片

在界面上创建一个 按钮

修改 widget.cpp, 给按钮设置图标.

执行程序, 观察效果

代码示例: 带有快捷键的按钮

在界面中拖五个按钮.

五个按钮的 objectName 分别为 pushButton_target , pushButton_up , pushButton_down , pushButton_left , pushButton_right 五个按钮的初始位置随意,

创建 resource.qrc , 并导入 5 个图片

修改 widget.cpp, 设置图标资源和快捷键

  • 使用 setShortcut 给按钮设置快捷键. 参数是一个 QKeySequence 对象. 表示一个按键序列. 支 持组合键 (ctrl + c 这种).
  • QKeySequence 的构造函数参数, 可以直接使用 "ctrl+c" 这样的按键名字符串表示, 也可以使用预定 义好的常量 (形如 Qt::CTRL + Qt::Key_C ) 表示.

运行程序, 此时点击按钮, 或者使用 ctrl+w,asd 均可让狗头移动

上面的代码,按住快捷键, 是可以进行重复触发的. 但是鼠标点击则不能

修改 widget.cpp, 在构造函数中开启重复触发.

此时, 按住鼠标时, 即可让狗头连续移动.

Radio Buttion

QRadioButton 是单选按钮. 可以让我们在多个选项中选择一个.

作为 QAbstractButton 和 QWidget 的子类, 上面介绍的属性和用法, 对于 QRadioButton 同样适用.

QAbstractButton 中和 QRadioButton 关系较大的属性

代码示例: 选择性别

在界面上创建一个 label, 和 3 个 单选按钮

设置的文本如下图. 3 个单选按钮的 objectName 分别为 radioButton_male , radioButton_female , radioButton_other

修改 widget.cpp, 编辑三个 QRadioButton 的 slot 函数.

运行程序, 可以看到随着选择不同的单选按钮, label 中的提示文字就会随之变化.

当前代码中, 如果程序启动, 则不会选择任何选项

可以修改代码, 让程序启动默认选中性别男

此时运行程序, 即可看到 性别男 已经被选中了.

当前代码中, 也可以禁用 "其他" 被选中.

修改 widget.cpp 的构造函数

运行程序, 可以看到, 点击 "其他" 按钮的时候, 虽然不会被选中, 但是可以触发点击事件, 使上面的 label 显示性别为其他.

使用 setEnabled 是更彻底的禁用按钮的方式. 此时该按钮无法被选中, 也无法响应任何输入

代码示例: click, press, release, toggled 的区别

  • clicked 表示一次 "点击"
  • pressed 表示鼠标 "按下"
  • released 表示鼠标 "释放"
  • toggled 表示按钮状态切换.

在界面上创建四个单选按钮

objectName 分别为 radioButton , radioButton_2 , radioButton_3 , radioButton_4

给 1 创建 clicked(bool) 槽函数, 给 2 创建 pressed 槽函数, 给 3 创建 released 槽函数, 给 4 创建 toggled 槽函数

运行程序, 可以看到

  • clicked 是一次鼠标按下+鼠标释放触发的.
  • pressed 是鼠标按下触发的.
  • released 是鼠标释放触发的.
  • toggled 是 checked 属性改变时触发的.

总的来说, toggled 是最适合 QRadioButton 的

代码示例: 单选框分组

在界面上创建 6 个单选框, 用来模拟麦当劳点餐界面

此时直接运行程序, 可以看到, 这六个 QRadioButton 之间都是排他的.

我们希望每一组内部来控制排他, 但是组和组之间不能排他.

引入 QButtonGroup 进行分组.

再次执行程序, 可以看到可以按照正确的分组方式来完成排他了

Check Box

QCheckBox 表示复选按钮. 可以允许选中多个

和 QCheckBox 最相关的属性也是 checkable 和 checked , 都是继承自 QAbstractButton .

至于 QCheckBox 独有的属性 tristate 用来实现 "三态复选框" . 这个东西比较冷门

代码示例: 获取复选按钮的取值

在界面上创建 三个复选按钮, 和一个普通按钮.

objectName 分别为 checkBox_study , checkBox_game , checkBox_work , 以及 pushButton

给 pushButton 添加 slot 函数

运行程序, 可以看到点击确认按钮时, 就会在控制台中输出选中的内容

Tool Button

QToolButton 的大部分功能, 和 QPushButton 是一致的. 但是 QToolButton 主要应用在工 具栏, 菜单等场景,这个暂时先不介绍

显示类控件

Label

QLabel 可以用来显示文本和图片

核心属性如下

代码示例: 显示不同格式的文本

在界面上创建三个 QLabel 尺寸放大一些. objectName 分别为 label, label_2, label_3

修改 widget.cpp, 设置三个 label 的属性

运行程序, 观察效果

纯文本中,#只是被单纯的当成了"文本" 。#在markdown里,则是一级标题。

代码示例: 显示图片

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

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

创建 resource.qrc 文件, 并把图片导入到 qrc 中

修改 widget.cpp, 给 QLabel 设置图片

执行程序, 观察效果

修改代码, 设置 scaledContents 属性

再次运行, 观察效果, 可以看到图片已经被拉伸, 可以把窗口填满了.

此时, 如果拖动窗口大小, 可以看到图片并不会随着窗口大小的改变而同步变化

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

执行程序, 此时改变窗口大小, 图片也会随之变化.于此同时, 在控制台里也能够看到尺寸变化的过程

注意:

此处的 resizeEvent 函数我们没有手动调用, 但是能在窗口大小变化时被自动调用.

这个过程就是依赖 C++ 中的多态来实现的. Qt 框架内部管理着 QWidget 对象表示咱们的窗 口. 在窗口大小发生改变时, Qt 就会自动调用 resizeEvent 函数.

但是由于实际上这个表示窗口的并非是 QWidget, 而是 QWidget 的子类, 也就是咱们自己写 的 Widget. 此时虽然是通过父类调用函数, 但是实际上执行的是子类的函数(也就是我们重写

后的 resizeEvent ).

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

代码示例: 文本对齐, 自动换行, 缩进, 边距

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

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

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

编写 widget.cpp, 给这四个 label 设置属性.

运行程序, 可以看到如下效果

代码示例: 设置伙伴

创建两个 label 和 两个 radioButton. objectName 分别问 label , label_2 , radioButton , radioButton_2

📍 此处把 label 中的文本设置为 "快捷键 &A" 这样的形式. 其中 & 后面跟着的字符, 就是快捷键. 可以通过 alt + A 的方式来触发该快捷键.

但是注意, 这里的快捷键和 QPushButton 的不同. 需要搭配 alt 和 单个字母的方式才能触 发.

编写 widget.cpp, 设置 buddy 属性

运行程序, 可以看到, 按下快捷键 alt + a 或者 alt + b, 即可选中对应的选项

LCD Number

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

核心属性

代码示例: 倒计时

在界面上创建一个 QLCDNumber , 初始值设为 10. objectName 为 lcdNumber

修改 widget.h 代码,

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

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

通过 intValue 获取到 QLCDNumber 内部的数值.

如果 value 的值归 0 了, 就停止 QTimer . 接下来 QTimer 也就不会触发 timeout 信号了

执行程序, 可以看到每隔一秒钟, 显示的数字就减少 1

针对上述代码, 存在两个问题:

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

显然, 这个代码是不行的. 循环会使 Widget 的构造函数无法执行完毕, 此时界面是不能正确构造和显示 的.

程序运行后,等了十秒,然后才显示界面,而且界面的数字是0

上述代码如果是在 Widget 构造函数中, 另起一个线程, 在新线程中完成 循环 + sleep 是否可以呢?

这个代码同样是不行的. Qt 中规定, 任何对于 GUI 上内容的操作, 必须在 主线程 中完成. 像 Widget 构造 函数, 以及 connect 连接的 slot 函数, 都是在主线程中调用的. 而我们自己创建的线程则不是.

当我们自己的线程中尝试对界面元素进行修改时, Qt 程序往往会直接崩溃.

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

比如调整了某个元素的尺寸, 就可能影响到内部的文字位置, 或者其他元素的位置. 这里一连串 的修改, 都是需要按照一定的顺序来完成的.

由于多线程执行的顺序无法保障, 因此 Qt 从根本上禁止了其他线程修改 GUI 状态, 避免后续的 一系列问题.

ProgressBar

使用 QProgressBar 表示一个进度条

核心属性

代码示例: 设置进度条按时间增长

在界面上创建进度条, objectName 为 progressBar

其中最小值设为 0, 最大值设为 100. 当前值设为 0.

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

修改 widget.cpp, 初始化 QTimer

  • 此处设置 100ms 触发一次 timeout 信号. 也就是一秒钟触发 10 次.

运行程序, 可以看到进度条中的进度在快速增长.

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

比如需要读取一个很大的文件, 就可以获取文件的总的大小, 和当前读取完毕的大小, 来设置进 度条的比例.

由于上面我们介绍了 Qt 禁止在其他线程修改界面, 因此进度条的更新往往也是需要搭配定时 器来完成的.

通过定时器周期触发信号, 主线程调用对应的 slot 函数. 再在 slot 函数中对当前的任务进度进 行计算, 并更新进度条的界面效果

代码示例: 创建一个红色的进度条

在界面上创建一个进度条.

在 Qt Designer 右侧的属性编辑器中, 找到 QWidget 的 styleSheet 属性.

编辑如下内容:

QProgressBar::chunk {background-color: red;}

其中的 chunk 是选中进度条中的每个 "块" . 使用 QProgressBar::text 则可以选中文本

同时把 QProcessBar 的 alignment 属性设置为垂直水平居中.

此处如果不设置 alignment , 进度条中的数字会跑到左上角. 这个怀疑是 Qt 本身的 bug, 暂时只能 先使用 alignment 来手动调整下.

执行程序, 可以看到如下效果. 我们就得到了一个红色的进度条

Calendar Widget

QCalendarWidget 表示一个 "日历" , 形如

核心属性

重要信号

代码示例: 获取选中的日期

在界面上创建一个 QCalendarWidget 和 一个 label objectName 为 calendarWidget , label

给 QCalendarWidget 添加 slot 函数

执行程序, 可以看到当选择不同的日期时, label 中的内容就会随之改变.

相关推荐
刃神太酷啦2 小时前
C++ list 容器全解析:从构造到模拟实现的深度探索----《Hello C++ Wrold!》(16)--(C/C++)
java·c语言·c++·qt·算法·leetcode·list
爬山算法2 小时前
Netty(14)如何处理Netty中的异常和错误?
java·前端·数据库
云和数据.ChenGuang2 小时前
自动化运维工程师之ansible启动rpcbind和nfs服务
运维·服务器·运维技术·数据库运维工程师·运维教程
yimengsama2 小时前
VMWare虚拟机如何连接U盘
linux·运维·服务器·网络·windows·经验分享·远程工作
松涛和鸣2 小时前
32、Linux线程编程
linux·运维·服务器·c语言·开发语言·windows
꧁坚持很酷꧂2 小时前
把虚拟机Ubuntu中的USB设备名称改为固定名称
linux·数据库·ubuntu
1024肥宅2 小时前
浏览器存储 API:全面解析与高级实践
前端·数据库·浏览器
水煎包V:YEDIYYDS8882 小时前
QT modbus 通信教程,把modbus封装到线程单例中,在线程内完成数据收发,解析。把重要数据以信号方式通知到qml层展示,解决UI卡顿
qt·modbus·线程服务
Evan芙2 小时前
Nginx 平滑升级
数据库·nginx·ubuntu