目录
[1. 控件概述和发展](#1. 控件概述和发展)
[2. QWidget 核心属性](#2. QWidget 核心属性)
[2.1 核心属性概览](#2.1 核心属性概览)
[2.2 enabled 是否可用](#2.2 enabled 是否可用)
[2.3 geometry 位置尺寸](#2.3 geometry 位置尺寸)
[2.4 windowTitle 标题](#2.4 windowTitle 标题)
[2.5 windowIcon 图标](#2.5 windowIcon 图标)
[2.6 windowOpacity 不透明度](#2.6 windowOpacity 不透明度)
[2.7 cursor 光标](#2.7 cursor 光标)
[2.8 font 字体](#2.8 font 字体)
[2.9 toolTip 鼠标悬停提示](#2.9 toolTip 鼠标悬停提示)
[2.10 focusPolicy 焦点策略](#2.10 focusPolicy 焦点策略)
[2.11 styleSheet 样式](#2.11 styleSheet 样式)
[3. 按钮类控件](#3. 按钮类控件)
[3.1 Push Button 按钮](#3.1 Push Button 按钮)
[3.2 Radio Buttion 单选按钮](#3.2 Radio Buttion 单选按钮)
[3.3 Check Box 复选按钮](#3.3 Check Box 复选按钮)
[4.4 Tool Button 工具栏按钮](#4.4 Tool Button 工具栏按钮)
1. 控件概述和发展

Widget 是 Qt 中的核心概念,英文原义是 "小部件",此处也把它翻译为 "控件"。控件是构成一个图形化界面的基本要素。

像上述示例中的按钮、列表视图、树形视图、单行输入框、多行输入框、滚动条、下拉框都可以称为 "控件"。
Qt 作为一个成熟的 GUI 开发框架,内置了大量的常用控件。这一点在 Qt Designer 中就可以看出来,并且 Qt 也提供了 "自定义控件" 的能力,可以让我们在现有控件不能满足需求的时候,对现有控件做出扩展,或者手搓出新的控件。

所以,学习 Qt 其中一个很重要的任务就是熟悉并掌握 Qt 内置的常用控件,这些控件对于我们快速开发出符合需求的界面是至关重要的。
控件体系的发展:
控件是 GUI 开发中的通用概念,不仅仅局限在 Qt 中。
第一阶段
完全没有控件。此时需要通过一些绘图 API 手动的绘制出按钮或者输入框等内容,代码编写繁琐。(例如文曲星的 Lava 平台开发)

第二阶段
只包含粗略的控件。只是提供了按钮 、输入框 、单选框 、复选框等最常用的控件。(例如 html 的原生控件)

第三阶段
更完整的控件体系,基本可以覆盖到 GUI 开发中的大部分场景。(例如早期的 MFC、VB、C++ Builder、Qt、Delphi、后来的 Android SDK、Java FX、前端的各种 UI 库等)

上图是前端中的 Element-ui 中的控件概览,无论是丰富程度还是颜值,都比 Qt 自带的控件更胜一筹。
2. QWidget 核心属性
在 Qt 中,使用 QWidget 类表示 "控件",像按钮、视图、输入框、滚动条等具体的控件类,都是继承自 QWidget。QWidget 中包含了 Qt 整个控件体系中通用的部分。
在 Qt Designer 中,随便拖一个控件过来,选中该控件,即可在右下方可以看到 QWidget 中的属性。

这些属性既可以通过 QtDesigner 直接修改,也可以通过代码的方式修改。这些属性的具体含义在 Qt Assistant 中均有详细介绍。
在 Qt Assistant 中搜索 QWidget,即可找到对应的文档说明(或者在 Qt Creator 代码中选中 QWidget,按 F1(+Fn) 也可)
2.1 核心属性概览
下列表格列出了 QWidget 中的属性及其作用:

下面会介绍上面列出的其中一些比较重要和常用的属性。
2.2 enabled 是否可用

所谓 "禁用" 指的是该控件不能接收任何用户的输入事件,并且外观上往往是灰色的。如果一个 widget 被禁用,则该 widget 的子元素也被禁用。
使用代码创建一个禁用状态的按钮:

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

通过按钮 2 切换按钮 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 是有规律的:控件的类型 + 下划线 + 数字。很明显,以数字的方式命名并不是一个好的编程习惯,这里我将它修改为如下所示:

生成两个按钮的 slot 函数
- 使用 isEnabled 获取当前按钮的可用状态。
- 使用 setEnabled 修改按钮的可用状态,此处是直接针对原来的可用状态进行取反后设置。

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

接着点击下方按钮,即可使上方按钮被禁用。

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

在 Qt Designer 中创建按钮的时候可以设置按钮的初始状态是 "可用" 还是 "禁用"。如果把 enabled 这一列的对钩去掉,则按钮的初始状态就是 "禁用" 状态。

2.3 geometry 位置尺寸
位置和尺寸是四个属性的统称:
- x 横坐标
- y 纵坐标
- width 宽度
- height 高度

但是实际开发中并不会直接使用这几个属性,而是通过一系列封装的方法来获取 / 修改。
对于 Qt 的坐标系,不要忘记是一个 "左手坐标系",其中坐标系的原点 是当前元素的父元素的左上角。


控制按钮的位置
(1) 在界面中拖五个按钮,五个按钮的 objectName 分别为:pushButton_target 、pushButton_up 、pushButton_down 、pushButton_left 、pushButton_right(五个按钮的初始位置和大小都随意)

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

运行程序可以看到:按下下方的四个按钮就会控制 target 的左上角的位置,对应的按钮整个尺寸也会发生改变。
上述代码是直接设置的 QRect 中的 x 和 y。实际上,QRect 内部是存储了左上和右下两个点的坐标,再通过这两个点的坐标差值计算长宽。单纯修改左上坐标就会引起整个矩形的长宽发生改变。

如果想让整个按钮都移动(宽度和高度不发生改变),可以不再修改 QRect,而是通过 QRect 基于 setGeometry 第二个版本的函数重新设置位置即可:

表白恶搞程序
(1) 往界面上拖拽两个按钮和一个 Label
Label 的 objectName 为 pushButton_accept 和 pushButton_reject,label 的 objectName 为 label 控件中文本如下图所示:

(2)在 widget.cpp 中添加 slot 函数

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

上述代码使用的是 clicked(一下一上是点击),如果使用 pressed(鼠标按下事件)。



如果使用 mouseMoveEvent,会更狠一些, 只要鼠标移动过来,按钮就跑了。对应的代码更麻烦一些,需要使用到 Qt 的事件机制(需要自定义类继承自 QPushButton,重写 mouseMoveEvent 方法)这里就暂时不展开了。
window frame 的影响
如果 widget 作为一个窗口(带有标题栏、最小化、最大化、关闭按钮),那么在计算尺寸和坐标的时候就有两种算法,包含 window frame 和不包含 window frame。
- 其中 x()、y()、frameGeometry()、pos()、move() 都是按照包含 window frame 的方式来计算的。
- 其中 geometry()、width()、height()、rect()、size() 则是按照不包含 window frame 的方式来计算的。
如果一个不是作为窗口的 widget,上述两类方式得到的结果是一致的。

相关 API

认真观察上面的表格,可以看到,其实这里的 API 有 frameGeometry 和 geometry 两个就足够完成所有的需求了。
为什么要提供这么多功能重复的 API 呢?
这个就涉及到 Qt API 的设计理念(尽量符合⼈的直觉)了,举例:Qt 的 QVector,尾插元素操作有以下方法:
- push_back
- append
- +=
- <<
上述方法的效果都是等价的,即使不翻阅文档,单纯的凭借直觉就能把代码写对。
geometry 和 frameGeometry 的区别
(1) 在按钮的 slot 函数中编写代码 & 在构造函数中也添加同样的代码

(2)执行程序
可以看到:在构造函数中打印出的 geometry 和 frameGeometry 是相同的。但是在点击按钮时,打印的 geometry 和 frameGeometry 则存在差异。

注意:在构造方法中,Widget 刚刚创建出来,还没有加入到对象树中,此时也就不具备 Window frame。
在按钮的 slot 函数中,由于用户点击的时候,对象树已经构造好了,此时 Widget 已经具备了 Window frame,因此在位置和尺寸上均出现了差异。
如果把上述代码修改成打印 pushButton 的 geometry 和 frameGeometry,结果就是完全相同的。因为 pushButton 并非是一个窗口。
2.4 windowTitle 标题

注意 :上述设置操作针对不同的 widget 可能会有不同的行为。
设置窗口标题
(1)修改 widget.cpp

执行效果:

2.5 windowIcon 图标

同 windowTitle,上述操作仅针对顶层 widget 有效。
设置窗口图标
先在 D 盘中保存一张图片,这里命名为 background1.jpg

修改 widget.cpp
前面推荐使用堆来创建对象,主要是因为要确保当前控件的生命周期是足够的,要通过 Qt 对象树来释放对象。
QIcon 自身是一个比较小的对象。创建出来之后,就是要设置到某个 QWidget 里面,QIcon 对象本身是否释放并不影响图标最终的显示。
QIcon 也不支持对象树,无法给它执行父对象。
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置图标
QIcon icon("d:/Videos+Photo/photo/background1.jpg");
// 设置窗口图标
this->setWindowIcon(icon);
}
Widget::~Widget()
{
delete ui;
}
运行程序可以看到窗口图标已经成为上述图片:

于此同时,程序在任务栏中的图标也发生改变:
实际开发中,一般不会在代码中通过绝对路径引入图片。因为我们无法保证程序发布后,用户的电脑上也有同样的路径。如果使用相对路径,则需要确保代码中的相对路径写法和图片实际所在的路径匹配。
- 绝对路径:以盘符(windows)或者以 /(Linux)开头的路径。
- 相对路径:以 .(表示当前路径)或者 以 ..(表示当前路径上级路径)开头的路径。其中,经常也会省略,相对路径的前提是需要明确 "当前工作目录"。
对于 Qt 程序来说,当前工作目录可能是变化的。比如通过 Qt Creator 运行的程序,当前工作目录是项目的构建目录,直接双击 exe 运行,工作目录则是 exe 所在目录。
所谓构建目录,是和 Qt 项目并列的,专门用来放生成的临时文件和最终 exe 的目录。
Qt 使用 qrc 机制帮我们自动完成了上述工作,更方便的来管理项目依赖的静态资源。这个机制可以从根本上解决以下两个问题:
- 确保我们的图片所在路径在目标用户机器上存在。
- 确保我们的图片不会被用户搞没了。
qrc 文件是一种 XML 格式的资源配置文件,它用 XML 记录硬盘上的文件和对应的随意指定的资源名称,应用程序通过资源名称来访问这些资源。在 Qt 开发中,可以通过将资源文件添加到项目中来方便地访问和管理这些资源,这些资源文件可以位于 qrc 文件所在目录的同级或其子目录下。
在构建程序的过程中,Qt 会把资源文件的二进制数据转成 cpp 代码,编译到 exe 中,从而使依赖的资源变得 "路径无关"。
这种资源管理机制并非 Qt 独有,很多开发框架都有类似的机制。例如:Android 的 Resources 和 AssetManager 也是类似的效果。
qrc 的缺点:无法导入太大的资源文件。
通过 qrc 管理图片作为图标
(1)右键项目,创建一个 Qt Resource File(qrc 文件)

文件名随意起(不要带中文和特殊符号即可),这里叫做:resource.qrc


(2)在 qrc 编辑器中添加前缀

此处前缀设置成 / 即可。所谓的前缀,可以理解成 "虚拟的目录",这个目录在我们的电脑中并不是真实存在的,是 Qt 自己抽象出来的,它决定了后续我们如何在代码中访问资源。
(3)在资源编辑器中,点击 add Files 添加资源文件
此处添加的是:background1.jpg:
注意 :添加的文件必须是在 qrc 文件的同级目录或者同级目录的子目录中,因此需要把之前 D 盘中的 background1.jpg 复制到上述目录中。
添加完毕后,可以在资源编辑器中看到添加好的文件:

在代码中使用 background1.jpg
编辑 widget.cpp
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 设置图标
// QIcon icon("d:/Videos+Photo/photo/background1.jpg");
QIcon icon(":/background1.jpg");
// 设置窗口图标
this->setWindowIcon(icon);
}
Widget::~Widget()
{
delete ui;
}
代码中需要访问 qrc 中管理的文件时,就需要在路径上带有 : 前缀。创建的前缀叫什么名字,代码中就写什么名字:前缀 + 文件名。
注意上述路径的访问规则:
- 使用 : 作为开头,表示从 qrc 中读取资源
- / 是上面配置的前缀
- rose.jpg 是资源的名称
需要确保代码中编写的路径和添加到 qrc 中资源的路径匹配,否则资源无法被访问(同时也不会有报错提示)。
运行程序可以看到图标已经能正确设置:

可以进入到项目的构建目录中可以看到:目录中多了一个 qrc_resource.cpp 文件,直接打开这个文件可以看到:
qrc 中导入的图片资源会被转成这个 qrc_resource.cpp(自动生成)这个 c++ 代码:

打开发现:

上述代码其实就是通过 unsigned char 数组,把 rose.jpg 中的每个字节都记录下来。这些代码会被编译到 exe 中,后续无论 exe 被复制到哪个目录下都确保能够访问到该图片资源。
上述 qrc 这一套资源管理方案的优点和缺点都很明显:
- 优点:确保了图片、字体、剩余等资源能够真正做到 "目录无关",无论如何都不会出现资源丢失的情况。
- 缺点:不适合管理体积大的资源。如果资源比较大(比如是几个 MB 的文件),或者资源特别多,生成的最终的 exe 体积就会比较大,程序运行消耗的内存也会增大,程序编译的时间也会显著增加。
2.6 windowOpacity 不透明度

调整窗口透明度演示:
(1)在界面上拖放两个按钮,分别用来增加不透明度和减少不透明度
objectName 分别为 pushButton_add 和 pushButton_sub:

(2)编写 wdiget.cpp, 编写两个按钮的 slot 函数
- 点击 pushButton_sub 会减少不透明度,也就是窗口越来越透明
- 点击 pushButton_add 会增加不透明度,窗口会逐渐恢复

(3)执行程序
点击了几下 '-' 之后,就可以透过窗⼝看到后面的内容了,点击 '+' 又会逐渐恢复。
同时控制台中也可以看到 opacity 数值的变化:

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

在 Qt Designer 中设置按钮的光标演示:
(1)在界面中创建一个按钮

(2)直接在右侧属性编辑区修改 cursor 属性为 "打开手势"

(3)运行程序
鼠标悬停到按钮上,即可看到光标的变化。
通过代码设置按钮的光标演示:
(1) 编写 widget.cpp
其中 Qt::WaitCursor 就是自带的沙漏 / 转圈形状的光标。

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

2.8 font 字体

关于 QFont:

在 Qt Designer 中设置字体属性演示
(1)在界面上创建一个 label

(2)在右侧的属性编辑区,设置该 label 的 font 相关属性
在这里调整上述属性,可以实时的看到文字的变化。

(3)执行程序

在代码中设置字体属性演示:
(1)编写 widget.cpp

(2)运行程序

在实际开发中,字体属性如何选择是一个 "审美问题",而不是 "技术问题",往往需要有一定的艺术细胞。幸运的是,公司中往往有专业的 "美工" / "设计" 这样的岗位,去做这方面的工作,程序员只要按照人家给的设计稿,把代码写出来即可,不必过多考虑怎样搭配才好看的问题。
2.9 toolTip 鼠标悬停提示

toolTip 只是给用户看的,在代码中一般不需要获取到 toolTip。
设置按钮的 toolTip:
(1)在界面上拖放两个按钮:objectName 设置为 pushButton_yes 和 pushButton_no

(2)编写 widget.cpp

(3)运行程序
观察效果,可以看到鼠标停到按钮上之后,就能弹出提示,时间到后自行消失。

2.10 focusPolicy 焦点策略
设置控件获取到焦点的策略,比如某个控件能否用鼠标选中或者能否通过 tab 键选中。
所谓 "焦点",指的就是能选中这个元素。接下来的操作(比如键盘操作),就都是针对该焦点元素进行的了。这个对于输入框、单选框、复选框等控件非常有用的。
这个事情就和 war3 或者 LOL 游戏中,先选中单位,再下达命令是一样的。



Qt::FocusPolicy 是一 个 枚举 类型,取值如下:
- Qt::NoFocus:控件不会接收键盘焦点
- Qt::TabFocus:控件可以通过 Tab 键接收焦点
- Qt::ClickFocus:控件在鼠标点击时接收焦点
- Qt::StrongFocus:控件可以通过 Tab 键和鼠标点击接收焦点(默认值)
- Qt::WheelFocus:类似于 Qt::StrongFocus,同时控件也通过⿏标滚轮获取到焦点(新增的选项, ⼀般很少使用)
理解不同的 focusPolicy
(1)在界面上创建四个单行输入框(Line Edit)

(2)修改四个输入框的 focusPolicy 属性为 Qt::StrongFocus(默认取值,一般不用额外修改)

此时运行程序可以看到,使用鼠标单击 / tab,就可以移动光标所在输入框,从而接下来的输入就是针对这个获取焦点的输⼊框展开的了。
(3)修改第二个输入框的 focusPolicy 为 Qt::NoFocus,则第二个输入框不会被 tab / 鼠标左键选中

此时这个输入框也就无法输入内容了。
(4)修改第二个输入框 focusPolicy 为 Qt::TabFocus,则只能通过 tab 选中,无法通过鼠标选中

(5)修改第二个输入框 focusPolicy 为 Qt::ClickFocus,则只能通过 tab 选中,无法通过鼠标选中

2.11 styleSheet 样式
通过 CSS设置 widget 的样式。
CSS(Cascading Style Sheets 层叠样式表)本身属于网页前端技术,主要就是用来描述界面的
样式。所谓 "样式",包括不限于大小、位置、颜色、间距、字体、背景、边框等。我们平时看到的丰富多彩的网页就都会用到大量的 CSS。
Qt 虽然是做 GUI 开发,但实际上和网页前端有很多异曲同工之处,因此 Qt 也引入了对于 CSS 的支持。CSS 中可以设置的样式属性非常多,基于这些属性 Qt 只能支持其中一部分,称为 QSS(Qt Style Sheet)。
设置文本样式演示:
(1)在界面上创建 label

(2)编辑右侧的 styleSheet 属性,设置样式

或者选择下面这种方式打开:


此处的语法格式同 CSS,使用键值对的方式设置样式。其中键和值之间使用 : 分割.,键值对之间使用 ; 分割。
另外,Qt Designer 只能对样式的基本格式进行校验,不能检测出哪些样式不被 Qt ⽀持,比如 text-align: center 这样的文本居中操作,就无法支持。
编辑完成样式之后,可以看到在 Qt Designer 中能够实时预览出效果:

(3)运行程序
可以看到实际效果和预览效果基本一致:

实现切换夜间模式 演示:
- 日间模式:文字是黑色的,背景是白色的
- 夜间模式:文字是白色的,背景是黑色的
(1)在界面上创建一个多行输入框(Text Edit)和两个按钮:objectName 分别为 pushButton_light 和 pushButton_dark

(2)编写按钮的 slot 函数
- #333 是深色,但是没那么黑
- #fff 是纯白色
- #000 是纯黑色
使用在线调色版或者画图板都可以看到数字对应的颜色,可参考:
在线调色板,调色板工具---在线工具 (sojson.com)

关于计算机中的颜色表示:
计算机中使用 "像素" 表示屏幕上的一个基本单位(也就是一个发亮的光点)。每个光点都使用三个字节表示颜色,分别是 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 色深等,实际情况会更加复杂。
(3)运行程序
- 点击 "日间模式" 就是浅色背景、深色文字
- 点击 "夜间模式" 就是深色背景、浅色文字


3. 按钮类控件
3.1 Push Button 按钮
使用 QPushButton 表示一个按钮,这也是当前我们最熟悉的一个控件了。QPushButton 继承自 QAbstractButton,这个类是一个抽象类,是其他按钮的父类。

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

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

- QAbstractButton 作为 QWidget 的子类,当然也继承了 QWidget 的属性。上面介绍的 QWidget 里的各种属性用法,对于 QAbstractButton 同样适勇。因此表格仅列出 QAbstractButton 独有的属性。
- Qt 的 api 设计风格是非常清晰的,此处列出的属性都是可以获取和设置的。例如,使用 text() 获取按钮文本,使用 setText() 设置文本。
事实上,QPushButton 的核心功能都是 QAbstractButton 提供的,自身提供的属性都比较简单。其中,default 和 audoDefault 影响的是按下 enter 时自动点击哪个按钮的行为,flat 把按钮设置为扁平的样式。
带有图标的按钮
(1)创建 resource.qrc 文件并导入图片
具体操作步骤参见 QWidget 中的 windowIcon部分。

在界面上创建一个按钮,修改 widget.cpp,给按钮设置图标
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 创建图标对象
QIcon icon(":/background1.jpg");
// 设置图标
ui->pushButton->setIcon(icon);
// 设置图标尺寸
ui->pushButton->setIconSize(QSize(50, 50));
}
Widget::~Widget()
{
delete ui;
}
观察结果:

带有快捷键的按钮,操作演示:
(1)在界面中拖五个按钮
五个按钮的 objectName 分别为 pushButton_target、pushButton_up、pushButton_down、pushButton_left、pushButton_right。

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

(3)修改 widget.cpp,设置图标资源和快捷键
使用 setShortcut 给按钮设置快捷键,参数是⼀个 QKeySequence 对象,表示一个按键序列,支持持组合键(Ctrl + C 这种)。
QKeySequence 的构造函数参数,可以直接使用 "Ctrl + C" 这样的按键名字符串表示,也可以使用预定义好的常量(形如 Qt::CTRL + Qt::Key_C)表示。

(4)修改 widget.cpp,设置四个方向键的 slot 函数

(5)运行程序点击按钮,或者使用 wasd 均可让 "柯南" 移动:

**按钮的重复触发:**在上述案例中按住快捷键,是可以进行重复触发的,但是鼠标点击则不能。
(1)修改 widget.cpp,在构造函数中开启重复触发

此时按住鼠标时,即可让 "柯南" 连续移动。
3.2 Radio Buttion 单选按钮
QRadioButton 是单选按钮,可以让我们在多个选项中选择一个。
作为 QAbstractButton 和 QWidget 的子类,上面介绍的属性和用法,对于 QRadioButton 同样适用。
QAbstractButton 中和 QRadioButton 关系较大的属性:

选择性别,操作演示
(1)在界面上创建⼀个 label 和 3 个单选按钮
设置的文本如下图,3 个单选按钮的 objectName 分别为:radioButton_male、radioButton_female、radioButton_other

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

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

(4)当前代码中,如果程序启动,则不会选择任何选项
可以修改代码,让程序启动默认选中性别男:

此时运行程序,即可看到性别男已经被选中了。
(5)当前代码中,也可以禁用 "其他" 被选中
修改 widget.cpp 的构造函数:

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

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


click、press、release、toggled 的区别:
- clicked 表示⼀次 "点击"
- pressed 表示鼠标 "按下"
- released 表示鼠标 "释放"
- toggled 表示按钮状态切换
区分演示:
(1)在界面上创建四个单选按钮
objectName 分别为 radioButton、radioButton_2、radioButton_3、radioButton_4

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

(3)运行程序
可以看到:
- clicked 是⼀次鼠标按下 + 鼠标标释放触发的
- pressed 是鼠标按下触发的
- released 是鼠标释放触发的
- toggled 是 checked 属性改变时触发的
总的来说,toggled 是最适合 QRadioButton 的。
单选框分组,操作演示:
(1)在界面上创建 6 个单选框,用来模拟麦当劳点餐界面。
objectName 分别为 radioButton 到 radioButton_6

此时直接运行程序可以看到,这六个 QRadioButton 之间都是排他的。我们希望每一组内部来控制排他,但是组和组之间不能排他。
(2)引入 QButtonGroup 进行分组
修改 widget.cpp

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

3.3 Check Box 复选按钮
QCheckBox 表示复选按钮,可以允许选中多个。和 QCheckBox 最相关的属性也是 checkable 和 checked,都是继承自 QAbstractButton。
至于 QCheckBox 独有的属性 tristate 用来实现 "三态复选框",这个比较冷门,这里暂时不讲述。
获取复选按钮的取值,操作演示:
(1)在界面上创建三个复选按钮和一个普通按钮
objectName 分别为 checkBox_study、checkBox_game、checkBox_work 以及 pushButton

(2)给 pushButton 添加 slot 函数

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

4.4 Tool Button 工具栏按钮
QToolButton 的大部分功能和 QPushButton 是一致的,但 QToolButton 主要应用在工具栏、菜单等场景。这里不做演示。
本篇完。
下一篇是Qt开发⑤Qt常用控件_中_显示类控件+输入类控件。