[QT]常用控件一
一:按钮类控件
Qt 中的按钮类控件是用户和GUI界面交互的核心元素,主要用于接收用户的点击操作并触发相应功能。这些控件均继承自QAbstractButton
基类,因此共享设置文本、图标、状态(启用 / 禁用、选中 / 未选中)等常用属性,同时通过信号与槽机制实现事件响应。
从功能和使用场景上划分,Qt 的按钮类控件可分为几大类:通用交互按钮(如QPushButton
)、工具栏专用按钮(如QToolButton
)、选择类按钮(如QRadioButton
、QCheckBox
)等。它们各自针对不同的交互需求进行了优化,例如单选按钮适合互斥选择,复选框适合多选项独立选择,而对话框按钮盒则简化了标准对话框的按钮布局与逻辑处理。接下来可以针对常见的按钮类型,详细介绍其特性、常用 API、使用场景及示例代码。
1.1:PushButton

作为 QWidget 的子类,QAbstractButton 自然也继承了 QWidget 的所有属性。我之前的博客介绍过的QWidget 的各种常用控件属性的用法,在QAbstractButton 中同样适用。因此上面的表格仅列出 QAbstractButton 特有的属性。
同时,Qt 的 API 设计风格十分清晰,这里列出的所有属性都支持获取和设置操作。例如,可通过 text () 接口获取按钮文本,通过 setText () 接口设置按钮文本。下面我们给出一些示例,来演示上述一些属性!
下面我们通过设置pushbutton的icon属性,来给我们的pushbutton按键设置图标,具体如下所示:
非常简单,利用之前学习过的控件属性和qrc机制很容易就能够设置pushbutton的图标。下面我们通过shortCut()这个api来给按钮设置对应的快捷键,具体如下所示:
#include "my_widget.h"
#include "ui_my_widget.h"My_Widget::My_Widget(QWidget *parent): QWidget(parent), ui(new Ui::My_Widget)
{ui->setupUi(this);//设置按钮图标ui->pushButton_target->setIcon(QIcon(":/my_image/laoshu.png"));ui->pushButton_target->setIconSize(QSize(100,100));ui->pushButton_up->setIcon(QIcon(":/my_image/up.png"));ui->pushButton_up->setIconSize(QSize(40,40));ui->pushButton_down->setIcon(QIcon(":/my_image/down.png"));ui->pushButton_down->setIconSize(QSize(40,40));ui->pushButton_left->setIcon(QIcon(":/my_image/left.png"));ui->pushButton_left->setIconSize(QSize(40,40));ui->pushButton_right->setIcon(QIcon(":/my_image/right.png"));ui->pushButton_right->setIconSize(QSize(40,40));//设置快捷键// ui->pushButton_up->setShortcut(QKeySequence("w"));// ui->pushButton_down->setShortcut(QKeySequence("s"));// ui->pushButton_left->setShortcut(QKeySequence("a"));// ui->pushButton_right->setShortcut(QKeySequence("d"));//快捷键和大小写没有区别// ui->pushButton_up->setShortcut(QKeySequence("W"));// ui->pushButton_down->setShortcut(QKeySequence("S"));// ui->pushButton_left->setShortcut(QKeySequence("A"));// ui->pushButton_right->setShortcut(QKeySequence("D"));//组合式快捷键可以直接写"xxx+xxx"的格式,但是这种直接写最多只能写两个组合键// ui->pushButton_up->setShortcut(QKeySequence("ctrl+w"));// ui->pushButton_down->setShortcut(QKeySequence("ctrl+s"));// ui->pushButton_left->setShortcut(QKeySequence("ctrl+a"));// ui->pushButton_right->setShortcut(QKeySequence("ctrl+d"));//虽然可以直接通过写方向键名称的方式来设置,但是容易写错,同时就算写错也不会报错,//因此为了安全考虑,我们可以使用Qt内置枚举的按键来设置快捷键//但是注意这里只有大写,// ui->pushButton_up->setShortcut(Qt::Key_W);// ui->pushButton_down->setShortcut(Qt::Key_S);// ui->pushButton_left->setShortcut(Qt::Key_A);// ui->pushButton_right->setShortcut(Qt::Key_D);//同样的,我们也可以设置成组合键,组合式快捷键可以直接写"xxx+xxx"的格式,ui->pushButton_up->setShortcut(Qt::CTRL | Qt::Key_W );ui->pushButton_down->setShortcut(Qt::CTRL | Qt::Key_S);ui->pushButton_left->setShortcut(Qt::CTRL | Qt::Key_A);ui->pushButton_right->setShortcut(Qt::CTRL | Qt::Key_D);//使用设置的键盘快捷键可以直接支持按钮重复触发,但是我们直接点击按键是不行的//所以我们需要设置AutoRepeat属性,ui->pushButton_up->setAutoRepeat(true);ui->pushButton_down->setAutoRepeat(true);ui->pushButton_left->setAutoRepeat(true);ui->pushButton_right->setAutoRepeat(true);
}My_Widget::~My_Widget()
{delete ui;
}void My_Widget::on_pushButton_up_clicked()
{QRect my_rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(my_rect.x(),my_rect.y()-5,my_rect.width(),my_rect.height());}void My_Widget::on_pushButton_down_clicked()
{QRect my_rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(my_rect.x(),my_rect.y()+5,my_rect.width(),my_rect.height());
}void My_Widget::on_pushButton_left_clicked()
{QRect my_rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(my_rect.x()-5,my_rect.y(),my_rect.width(),my_rect.height());
}void My_Widget::on_pushButton_right_clicked()
{QRect my_rect = ui->pushButton_target->geometry();ui->pushButton_target->setGeometry(my_rect.x()+5,my_rect.y(),my_rect.width(),my_rect.height());
}
上述示例借助四个按键来控制一个对象的移动,并且为每个按钮都设置了图标。同时,通过 shortcut()
为这四个按键设置了快捷键。快捷键的设置主要有两种方式,一种是直接自行编写快捷键名称,这种方式虽然简单,但即便写错,Qt 也不会报错;另一种是使用 Qt 内置枚举的快捷键,这种方式的检查更为严格。此外,由于设置的快捷键默认支持重复触发,所以当我们长按快捷键时,对应的目标就会持续移动。然而,要是我们一直用鼠标点击按键,是不会重复触发的,所以我们需要通过 AutoRepeat()
来为点击按键设置重复触发功能。
1.2:RadioButton
QRadioButton 是单选按钮. 可以让我们在多个选项中选择⼀个.,继承自 QAbstractButton 和 QWidget,完整继承了两者的属性与功能。它继承 QAbstractButton 的状态切换、事件响应等特性,支持 setText ()、setChecked () 等方法;作为 QWidget 子类,支持用户与GUI界面交互控制等。其核心是单选机制。所以在使用中,我们还是比较关心QAbstractButton 中和 QRadioButton 关系较⼤的属性,如下所示:
下面给出示例,通过示例来展现radiobutton的属性,具体如下所示:
先放三个单选按钮(RadioButton),大家能看到,只要选中了其中一个,再点其他按钮就选不上了,这正好体现了单选按钮 “只能选一个” 的排他性。接下来,我们再进一步给大家看具体的示例,内容如下:
运行程序后能看到,通过设置 checkable (),点击 "测试" 按钮时,它虽然不会被选中,却能触发点击事件,让上面的 label 显示 "测试"。要是想“禁用”这个按钮,除了不让它被选中,还能利用 QWidget 里的 enabled () 属性,彻底把 "测试" 按钮禁用掉,具体做法如下:

单选按钮(RadioButton)默认是 “排他” 的,意思是任何时候都只允许一个按钮被勾选。但在有些情况下,这种默认的排他效果就不符合我们的需求了,具体情况如下所示:
当界面上需要存在“多组”单选按钮的情况时,radiobutton默认的排他机制就不适合了,我们希望组与组之间不要互相干扰,组内保存默认排他即可,因此,我们引入QButtonGroup类,针对单选按钮进行分类,具体使用如下所示:
通过这样的分组,利用QButtonGroup就可以让不同类别的单选按钮各自独立互斥,比如选 “性别” 里的 “男”,不影响 “年龄” 里选 “青年”、“民族” 里选 “汉族”。
1.3:CheckBox/ToolButton
前面我们已经了解了单选按钮(RadioButton),接下来看看多选按钮(QCheckBox)。QCheckBox 是复选按钮,允许同时选中多个选项。和 QCheckBox 关系最密切的属性也是 checkable 和 checked,这两个都是从 QAbstractButton 继承来的。至于 QCheckBox 特有的 tristate 属性,它是用来实现 "三态复选框" 的。这个功能比较冷门,我们暂时先不讨论。下面给出一个示例,来看看如何使用复选按钮,具体如下所示:
除了按钮(PushButton)、单选按钮(RadioButton)、复选按钮(CheckBox)之外,还有一种按钮类控件叫 QToolButton。QToolButton 的大部分功能和 QPushButton 是一样的,但它主要用在工具栏、菜单这类场景里。不过这些场景我们目前还没学到,先不展开说。
二:显示类控件
2.1:label
显示类控件最重要的就是QLabel ,而QLabel 可以用来显示文本和图片。它功能多样,既能显示普通文本,也能展示富文本(带格式的文字),还支持显示图片(如 QPixmap、QImage 格式)。通过设置相关属性,可调整文本对齐方式(左对齐、居中、右对齐)、换行方式,以及是否是否允许文本选中、是否可复制等。
QLabel 通常不直接用户直接交互,主要起展示信息的作用,常配合输入框、按钮等控件使用,比如在输入框前显示 “用户名:” 这样的提示文字,让界面更易理解。下面给出Qlabel常用的api,具体如下所示:
接下来我将介绍使用上述表中的一些api,下面给出具体示例,如下所示:
从上面的例子能看出来,QLabel 支持好几种文本格式。只要给 QLabel 设置了某种文本格式,那么写在 QLabel 里的文字,就都会按照这个格式来显示和解读!
下面再给出一个示例,让QLabel里面能够展示图片,具体如下所示:
通过上述示例能看到,我们用 pixmap () 可以给 QLabel 设置图片,但图片的尺寸好像不是我们想要的 —— 这主要是因为图片本身的大小有限制。现在导入的这张图片太小了,填不满整个窗口,所以为了让图片能铺满整个窗口或者 QLabel,我们得用 scaledContents () 这个接口,把图片拉伸一下,具体做法如下所示:

这是因为我们在构造函数里设置了 QLabel 的大小,这种设置是 “一次性” 的 —— 程序一运行,QLabel 的尺寸就固定了。之后就算拖动窗口改变大小,窗口能变,但 QLabel 的尺寸不会跟着变,所以图片也就不会随窗口大小变化了。
要是想让图片跟着窗口一起变,就得让图片尺寸能随时调整。这时候就要用到 “事件” 这个概念了。
在 Qt 里,用户的操作会有对应的处理,操作分两种:一种是信号,比如点击按钮;另一种是事件,比如拖拽窗口时窗口大小不断变化。拖拽窗口这种行为会触发 resize 事件(resizeEvent),而且是连续触发的 —— 从 A 尺寸拖到 B 尺寸的过程中,会触发一连串的 resize 事件。
所以想让图片实时变化,就可以用 resize 事件来实现:让 Widget 窗口类重写父类 QWidget 的 resizeEvent 虚函数。这样拖拽窗口时,就会连续触发 resize 事件,每次触发都会调用我们重写的这个函数(这是多态的效果,子类调用父类的虚函数就会调用自己重写的函数)。然后在这个重写的函数里,我们实现图片尺寸的实时调整就行,具体做法如下所示:
由上可知,当我们在窗口类 Widget 里重写了 resizeEvent 函数后,通过 qDebug 打印的内容可以发现,窗口大小会跟着我们的拖拽实时变化。这样一来,我们只需要在这个重写的虚函数里面,设置图片的尺寸大小就行了,具体做法如下所示:
现在图片的大小就能实时跟着变化了!接下来我们继续介绍 QLabel 里的其他属性和 API,比如 QLabel 的边框、文本对齐方式、自动换行、缩进、边距这些,具体内容如下所示:
在 QLabel 里,我们还能给标签设置边框,直接在 Qt 的 ui 界面操作 QFrame 就行,因为 QFrame 是 QLabel 的父类。其中 frameShape 这个属性是用来设置边框样式的,具体的边框属性有这些:
QFrame::Box:矩形边框 QFrame::HLine:水平线边框 QFrame::VLine:垂直线边框 QFrame::WinPanel:Windows 风格的边框 QFrame::Panel:带可点击区域的面板边框QFrame::StyledPanel:带有可点击区域的面板边框,但样式取决于窗口主题!!!
接下来我们给QLabel设置对齐方式,具体如下所示:
可以看到,在 Qt 中,各种对齐方式已经用枚举列出来了。当我们需要设置对齐方式时,只需通过 Alignment()来设置就行。至于QLabel 中的自动换行、缩进、边距这些,只需要通过API设置即可,具体如下所示:
QLabel 还能和其他输入控件进行绑定,这叫 “伙伴绑定”,也就是 Qt 中建立 “伙伴关系” 的方法。建立关联后,当用户按下标签中带下划线的快捷键(通常在文本里加 & 符号设置,比如 "&A"),对应的输入控件就会自动获得焦点,方便用户快速切换到该输入框操作,提高交互效率。
比如,有一个标签 label 和输入框 lineEdit,用 label->setBuddy (lineEdit) 关联后,用户按 Alt+N(假设标签文本是 "&Name:"),光标就会自动定位到 lineEdit 上。下面给出一个具体示例,如下所示:

2.2:QLCDNumber

这里面需要注意的就是设置value时的api,不是一般认为的setvalue(),而是display(),下面给出具体运用示例,如下所示:
上面我们给出了一个用 LCDNumber 来显示倒计时的效果,其关键是如何让其周期性的减一,而在实际中,这种能周期性的执行某一种逻辑的组件我们一般称之为定时器!一般在 C++ 标准库中是没有提供定时器的实现,但是在 boost 库中提供了定时器功能,而 Qt 中也封装了对应的定时器,省得自己再去实现定时器比较麻烦,Qt 中提供的定时器叫做 QTimer 类,而且Qt 还将它和信号槽机制完美的结合起来,通过 QTimer 类生成的对象,在使用时就会产生一个 timeout 信号,此时我们可以通过 QTimer 类中提供的 start () 方法来开启定时器,同时通过里面的参数设置触发 timeout 信号的周期!
这样,每一次触发 timeout 信号,通过 QTimer 和信号槽机制的绑定,就可以让我们周期性的去执行某些操作了!
那么除了使用定时器来实现倒计时的效果,能不能使用 C++ 库中的 sleep 函数来实现呢?在学习 C++ 线程部分时,我们引入过 sleep_for (),那么接下来我们试着用 sleep_for () 来完成上述倒计时操作,具体如下所示:
#include "my_widget.h"
#include "ui_my_widget.h"
#include <thread>My_Widget::My_Widget(QWidget *parent): QWidget(parent), ui(new Ui::My_Widget)
{ui->setupUi(this);//设置初始值ui->lcdNumber->display(10);int my_value=ui->lcdNumber->intValue();while(true){//使用C++线程库中的sleep_for函数//std::chrono::seconds:按秒进行休眠!std::this_thread::sleep_for(std::chrono::seconds(1));if(my_value<=0){break;}my_value-=1;ui->lcdNumber->display(my_value);}
}
如上所示,虽然我们可以使用线程库中的 sleep_for 函数实现休眠,但是运行程序会发现,运行后过 “一段” 时间运行结果才出现,而且倒计时结果直接到 0,这是为什么呢?其原因就在于这是我们在构造函数中实现的,只有构造函数执行完,运行结果才能 show () 出来,而我们直接在构造函数中进行循环,所以就会出现上述情况。既然无法在主线程构造函数内使用 sleep_for 实现倒计时效果,那么我们能不能重新开一个线程,让另一个线程执行倒计时操作,这样也不会影响到主线程的构造呢?具体如下所示:
我们可以看到,当在构造函数中另起线程并使用 lambda 表达式作为回调函数时,程序会出现终止报错,这是为什么呢?
因为在Qt中规定,所有对 GUI 内容的操作都必须在主线程中完成。像 Widget 构造函数以及 connect 连接的 slot 函数,都是在主线程中调用的,而我们自己创建的线程则不在此列。当自定义线程尝试修改界面元素时,Qt 程序往往会直接崩溃。
这样的约定主要是因为 GUI 中的状态通常牵一发而动全身,修改一个地方,就需要同步调整其他内容。例如调整某个元素的尺寸,可能会影响内部文字位置或其他元素的位置,这一系列修改都需要按特定顺序完成。由于多线程的执行顺序无法保障,Qt 从根本上禁止其他线程修改 GUI 状态,以避免后续一系列问题。
综上所述,使用定时器是实现上述功能的最合理方案。后续若有类似 “周期性修改界面状态” 的需求,也应优先考虑使用定时器!!!
2.3:ProgressBar
在 Qt 中,QProgressBar 是用于显示任务进度的控件,常用来直观呈现操作的完成情况。比如执行某些任务时,不能让用户无端等待,我们需要告知用户当前是需继续等待还是程序已卡住,以便用户直观了解程序的运行状态,下面提供 QProgressBar 相关的 API,具体内容如下所示:
下面我们给出一个例子,使用定时器来实现进度条按照时间的方式进行增加,具体如下所示:
在实际开发中,进度条的取值通常要依据当前任务的实际进度来设置。这里我们是通过定时器来实现设置的,在其他情况下,比如需要读取一个较大的文件时,就可以获取文件的总大小与当前已读取的大小,据此设定进度条的比例。
由于前面已介绍过 Qt 禁止在其他线程中修改界面,所以进度条的更新往往也需要配合定时器来实现。通过定时器周期性地触发信号,主线程会调用对应的 slot 函数,再在 slot 函数中计算当前的任务进度,并更新进度条的界面显示效果。
别忘了,QProgressBar 同样是 QWidget 的子类,因此我们可以利用 styleSheet 属性通过样式表修改进度条的颜色。只需在 Qt Designer 右侧的属性编辑器中,找到 QWidget 的 styleSheet 属性,打开样式表并写入 QProgressBar::chunk {background-color: #FF0000/black;},其中 chunk 指的是进度条中选中的每个 “块”。若要选中文本,可使用 QProgressBar::text;同时需将 QProgressBar 的 alignment 属性设置为垂直水平居中,因为若不设置该属性,进度条中的数字会跑到左上角。这一点怀疑是 Qt 自身的 bug,目前暂时只能通过 alignment 手动调整。通过上述方式,我们也能依样修改文字的颜色、字体大小等样式。
2.4:Calendar Widget
在 Qt 中,QCalendarWidget
是一款功能完整的日历控件,用于在界面中提供可视化的日期选择与展示功能,支持日期导航、选中、范围限制等核心操作,常应用于需要用户选择日期的场景(如日程安排、数据筛选、预约系统等)。下面提供 calendar widhet 相关的 API,具体内容如下所示:
下面给出一个示例,了解如何使用即可,具体如下所示:
三:输入类控件
3.1:Line Edit
不同于显示类控件,输入类控件既能展示内容,也能让用户输入信息。在众多输入类控件里,我们使用最频繁的便是 QLineEdit。它是基础且常用的单行文本输入控件,主要用于接收用户的单行文本输入(如账号、密码、搜索关键词等),但输入时不支持换行,同时具备文本编辑、格式限制、输入校验等功能,是界面交互中必不可少的组件。下面提供Line Edit相关的 API,具体内容如下所示:
下面我们给出一个示例,展示这些api里面比较常用的几个,具体如下所示:
前面我们实现了一个收集个人信息的小示例,展示了一些常用 API 的用法,同时也能发现 inputmask () 在格式限制方面过于简单。那么有没有更灵活的格式限制方式呢?在实际开发中,基于正则表达式的方式才是更核心的格式限制方法!那什么是正则表达式呢?正则表达式是计算机中常用的一种机制,本质上是带有特殊字符的字符串,它通过这些特殊字符描述另一字符串的特征,借此就能用正则表达式来界定一些具有特定格式的字符串,在字符串匹配场景中十分实用。正则表达式的语法相对复杂,通常不需要记忆,而是随用随查。下面给出正则表达式文档:https://learn.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2008/ae5bf541(v=vs.90)?redirectedfrom=MSDN
接下来,我们通过正则表达式来限制格式,具体样例如下所示:
使用正则表达式来限制格式的样例如上所示,都在图中,下面我们再给出一个简单的例子,继续学习使用textEdited信号,具体如下所示:
My_Widget::My_Widget(QWidget *parent): QWidget(parent), ui(new Ui::My_Widget)
{ui->setupUi(this);ui->lineEdit->setEchoMode(QLineEdit::Password);ui->lineEdit->setClearButtonEnabled(true);ui->lineEdit_2->setEchoMode(QLineEdit::Password);ui->lineEdit_2->setClearButtonEnabled(true);
}void My_Widget::comper()
{QString str1=ui->lineEdit->text();QString str2 =ui->lineEdit_2->text();if(str1==""&&str1==""){ui->label->setText("密码为空!!!");}else if(str1==str2){ui->label->setText("密码匹配成功!!!");}else{ui->label->setText("密码匹配失败!!!");}
}void My_Widget::on_lineEdit_textEdited(const QString &arg1)
{(void)arg1;
My_Widget::comper();
}void My_Widget::on_lineEdit_2_textEdited(const QString &arg1)
{(void)arg1;My_Widget::comper();
}
3.2:Text Edit
上述我们学习了单行输入框QLineEdit
,但有时我们需要输入多行内容,所以接下来学习多行输入框。多行输入框分为两种,一种是QTextEdit
,另一种是QPlainTextEdit
,二者的区别在于QPlainTextEdit
只能处理纯文本输入,QTextEdit
则还支持 HTML 和 Markdown 格式的文本!至于其他属性大致相同,因此此处我们就以QTextEdit
为例,学习多行输入框,其具体的 API 如下所示:
在单行输入框中我们一直在使用textEdited
信号,接下来在多行输入框中,我们尝试使用与textEdited
信号相关的textChanged()
信号。下面给出一个示例,展示textChanged()
信号的具体使用,具体内容如下所示:
我们可以看到,当在 UI 界面将 textEdit 关联到 textChanged () 信号的槽函数后,只需获取多行输入框中的内容,再将其设置到标签栏中,就能实时获取多行输入框的内容!下面我们试着了解TextEdit中的其他信号,具体如下所示:
//⽂本内容改变时触发:
void My_Widget::on_textEdit_textChanged()
{qDebug()<<"textChanged()信号:"<<ui->textEdit->toPlainText();
}//选中范围改变时触发:鼠标选中字符时触发
void My_Widget::on_textEdit_selectionChanged()
{//QTextEdit 中包含了⼀个 QTextCursor 对象, 通过这个对象可以获取到当前光标位置和选中的内容.QTextCursor my_cursor=ui->textEdit->textCursor();qDebug()<<"selectionChanged()信号:"<<my_cursor.selectedText();
}//光标移动时触发:
void My_Widget::on_textEdit_cursorPositionChanged()
{QTextCursor my_cursor=ui->textEdit->textCursor();qDebug()<<"cursorPositionChanged()信号:"<<my_cursor.position();
}//可以进⾏undo操作时触发:就是ctrl+z时触发
void My_Widget::on_textEdit_undoAvailable(bool b)
{qDebug()<<"undoAvailable(bool b)信号:"<<b;
}//可以进⾏ redo 操作时触发:恢复
void My_Widget::on_textEdit_redoAvailable(bool b)
{qDebug()<<"redoAvailable(bool b)信号:"<<b;
}//⽂本被选中/取消选中时触发
void My_Widget::on_textEdit_copyAvailable(bool b)
{qDebug()<<"copyAvailable(bool b)信号:"<<b;
}
我们可以看到,在 UI 界面将 textEdit 关联到其各种信号的槽函数进行打印测试时,上述图只展示了部分信号被触发时打印的信息。由于有些信号的打印效果不好讲解,这里就不详细介绍了,大家可以复制上述代码自行测试打印结果。
四:总结
由于 Qt 中的控件及控件属性数量较多,我无法一次性介绍完所有控件和属性,所以这里先简单介绍按钮类、显示类以及部分输入类控件,下篇博客我会继续从输入类控件开始学习。至此,以上就是我对这些控件的介绍,若存在不足之处,欢迎各位批评指正!谢谢!!!