Qt 常用控件详解:按钮类 / 显示类 / 输入类属性、信号与实战示例

文章目录

    • 一、按钮类控件
      • [3.1 PushButton(普通按钮)](#3.1 PushButton(普通按钮))
      • [3.2 RadioButton(单选按钮)](#3.2 RadioButton(单选按钮))
      • [3.3 CheckBox(复选按钮)](#3.3 CheckBox(复选按钮))
      • [3.4 ToolButton(工具按钮)](#3.4 ToolButton(工具按钮))
    • 二、显示类控件
      • [4.1 Label(文本/图片显示)](#4.1 Label(文本/图片显示))
      • [4.2 LCDNumber(数字显示)](#4.2 LCDNumber(数字显示))
      • [4.3 ProgressBar(进度条)](#4.3 ProgressBar(进度条))
      • [4.4 CalendarWidget(日历控件)](#4.4 CalendarWidget(日历控件))
    • 三、输入类控件
      • [5.1 LineEdit(单行输入框)](#5.1 LineEdit(单行输入框))
      • [5.2 TextEdit(多行输入框)](#5.2 TextEdit(多行输入框))
      • [5.3 ComboBox(下拉框)](#5.3 ComboBox(下拉框))
      • [5.4 SpinBox(微调框)](#5.4 SpinBox(微调框))
      • [5.5 Date Edit & Time Edit (日期/时间)](#5.5 Date Edit & Time Edit (日期/时间))
      • [5.6 Dial(旋钮)](#5.6 Dial(旋钮))
      • [5.7 Slider(滑动条)](#5.7 Slider(滑动条))

一、按钮类控件

按钮类控件继承自 QAbstractButton(抽象类),核心功能由父类提供,包括文本、图标、快捷键、重复触发等属性,Qt 常用按钮控件有 PushButton、RadioButton、CheckBox、ToolButton。


常用槽函数:

名称(标准写法) 使用方法
click() 作为成员函数直接调用(如 btn->click()),主动模拟按钮完整点击动作,会触发 pressed()released()clicked() 系列信号。
clicked() 作为信号,通过 connect 绑定自定义槽函数(如 connect(btn, &QPushButton::clicked, this, &MyClass::onBtnClicked)),响应按钮完成点击的事件。
clicked(bool) 作为信号,通过 connect 绑定带 bool 参数的槽函数(如 connect(btn, &QPushButton::clicked, this, &MyClass::onBtnChecked)),响应可复选按钮点击后的状态变化。
pressed() 作为信号,通过 connect 绑定槽函数(如 connect(btn, &QPushButton::pressed, this, &MyClass::onBtnPressed)),响应按钮按下瞬间的事件。
released() 作为信号,通过 connect 绑定槽函数(如 connect(btn, &QPushButton::released, this, &MyClass::onBtnReleased)),响应按钮在区域内松开的事件。
toggle() 作为成员函数直接调用(如 btn->toggle()),主动反转可复选按钮的选中状态;也可作为槽函数绑定到其他信号(如 connect(ctrlBtn, &QPushButton::clicked, btn, &QPushButton::toggle)),通过其他信号触发状态切换。

3.1 PushButton(普通按钮)

核心属性(继承自 QAbstractButton):

属性 说明
text 按钮文本
icon / iconSize 按钮图标及尺寸
shortcut 快捷键(支持组合键,如 Ctrl+C)
autoRepeat 按住时是否重复触发(类似"连发")
autoRepeatDelay 重复触发延迟时间(ms)
autoRepeatInterval 重复触发周期(ms)
  • 代码示例1:带有图标的按钮
  1. 拖放 1 个 pushbutton;
  2. 编写代码:
cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->pushButton->setIcon(QIcon(":/image/favicon.png"));
	ui->pushButton->setIconSize(QSize(50,50));  
}
  • 代码示例2:带有快捷键的按钮
  1. 在ui界⾯中拖五个按钮, objectName 分别为 pushButton_target / up / down / left / right
  2. 创建resource.qrc
  3. 绑定快捷键,编写代码:
cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->pushButton->setIcon(QIcon(":/image/favicon.png"));
    ui->up->setIcon(QIcon(":/image/up.png"));
    ui->down->setIcon(QIcon(":/image/down.png"));
    ui->left->setIcon(QIcon(":/image/left.png"));
    ui->right->setIcon(QIcon(":/image/right.png"));

    ui->pushButton->setIconSize(QSize(50,50));
    ui->up->setIconSize(QSize(50,50));
    ui->down->setIconSize(QSize(50,50));
    ui->left->setIconSize(QSize(50,50));
    ui->right->setIconSize(QSize(50,50));

    ui->up->setShortcut(QKeySequence(Qt::Key_W+ Qt::CTRL));
    ui->down->setShortcut(QKeySequence(Qt::Key_S));
    ui->left->setShortcut(QKeySequence(Qt::Key_A));
    ui->right->setShortcut(QKeySequence(Qt::Key_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"));
}

3.2 RadioButton(单选按钮)

属性 说明
checkable 是否能选中
checked 是否已经被选中。checkable 是 checked 的前提条件。
autoExclusive 是否排他。选中一个按钮之后是否会取消其他按钮的选中。对于 QRadioButton 来说默认就是排他的。
  • 代码示例1:选择(默认选中"男")
  1. 拖放 3 个 RadioButton(objectName:radioButton_male/female/other)和 1 个 Label;
  2. 编写代码:
cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->radioButton_male->setChecked(true); // 默认选中男
    ui->label->setText("你选择的性别为: 男");
}
// 男按钮槽函数
void Widget::on_radioButton_male_clicked()
{
    ui->label->setText("你选择的性别为: 男");
}
// 女按钮槽函数
void Widget::on_radioButton_female_clicked()
{
    ui->label->setText("你选择的性别为: 女");
}
  • 代码示例2:单选按钮分组(使用 QButtonGroup 实现多组排他)
cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 创建三个分组
    QButtonGroup* group1 = new QButtonGroup(this); // 1组
    QButtonGroup* group2 = new QButtonGroup(this); // 2组
    QButtonGroup* group3 = new QButtonGroup(this); // 3组
    // 添加按钮到分组
    group1->addButton(ui->radioButton);
    group1->addButton(ui->radioButton_2);
    group2->addButton(ui->radioButton_3);
    group2->addButton(ui->radioButton_4);
}

3.3 CheckBox(复选按钮)

  • 支持多选 ,核心属性同 RadioButton(checkable/checked),独有的 tristate 属性可实现三态复选(较少用)。
  • 代码示例:获取选中的复选框内容
  1. 拖放 3 个 CheckBox(吃饭/睡觉/打豆豆)和 1 个确认按钮;
  2. 编写确认按钮槽函数:
cpp 复制代码
void Widget::on_pushButton_clicked()
{
    QString result;
    if (ui->checkBox_eat->isChecked()) result += ui->checkBox_eat->text();
    if (ui->checkBox_sleep->isChecked()) result += ui->checkBox_sleep->text();
    if (ui->checkBox_play->isChecked()) result += ui->checkBox_play->text();
    qDebug() << "选中的内容: " << result;
}

3.4 ToolButton(工具按钮)

  • 使用较少,后续可能会进行讲解...

二、显示类控件

显示类控件用于展示文本、图片、数字、进度等信息,常用控件包括 Label、LCDNumber、ProgressBar、CalendarWidget。

4.1 Label(文本/图片显示)

属性 说明
text / textFormat 文本内容及格式(纯文本、富文本、Markdown) [Qt::PlainText、Qt::RichText、Qt::MarkdownText]
pixmap / scaledContents 显示图片及是否自动拉伸填充
alignment 文本/图片对齐方式
wordWrap 是否自动换行
indent / margin 文本缩进(水平/垂直)/ 内边距(上下左右)
openExternalLinks 是否允许打开文本中的外部链接
buddy 关联伙伴控件(点击 Label 激活伙伴,如选中复选框)
  • 代码示例1:显示不同格式文本
cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 纯文本
    ui->label->setTextFormat(Qt::PlainText);
    ui->label->setText("这是一段纯文本");
    // 富文本(支持 HTML 标签)
    ui->label_2->setTextFormat(Qt::RichText);
    ui->label_2->setText("<b>这是一段富文本</b>");
    // Markdown 文本
    ui->label_3->setTextFormat(Qt::MarkdownText);
    ui->label_3->setText("## 这是一段 Markdown 文本");
}
  • 代码示例2:显示图片并自适应窗口大小(由于图片只会自适应窗口一次,再次改变窗口大小则需要重写resizeEvent函数来自适应)
cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setGeometry(0, 0, this->width(), this->height());
    QPixmap pixmap(":/favicon.png");
    ui->label->setPixmap(pixmap);
    ui->label->setScaledContents(true); // 自动拉伸
}
// 重写 resizeEvent 实现窗口缩放时图片同步调整
void Widget::resizeEvent(QResizeEvent *event)
{
    ui->label->setGeometry(0, 0, event->size().width(), event->size().height());
}

重写resizeEvent之前:

重写resizeEvent之后:

  • 代码实例3:label设置边框

直接通过designer ui属性界面即可设置:

frameShape属性值 说明
QFrame::Box 矩形边框
QFrame::Panel 带有可点击区域的面板边框
QFrame::WinPanel Windows风格的边框
QFrame::HLine 水平线边框
QFrame::VLine 垂直线边框
QFrame::StyledPanel 带有可点击区域的面板边框,但样式取决于窗口主题
  • 代码示例4:设置文字对齐方式、自动换行
分类 枚举值 中文说明 核心特点/适用场景
水平对齐 Qt::AlignLeft 左对齐 默认值,文本/控件靠左侧显示(常规排版)
水平对齐 Qt::AlignRight 右对齐 文本/控件靠右侧显示(如数值、金额)
水平对齐 Qt::AlignHCenter 水平居中 文本/控件水平方向居中(最常用)
水平对齐 Qt::AlignJustify 两端对齐 仅多行文本生效,拉伸行宽填满控件宽度
垂直对齐 Qt::AlignTop 顶部对齐 文本/控件靠顶部显示(段落文本)
垂直对齐 Qt::AlignBottom 底部对齐 文本/控件靠底部显示(角落提示)
垂直对齐 Qt::AlignVCenter 垂直居中 文本/控件垂直方向居中(按钮文本)
垂直对齐 Qt::AlignBaseline 基线对齐 对齐文本基线(仅文本类控件生效,如QLabel)

常用组合对齐示例:

组合枚举值 中文说明 典型应用场景
Qt::AlignLeft | Qt::AlignTop 左上对齐 常规标签、段落文本(如QLabel长文本)
Qt::AlignRight | Qt::AlignBottom 右下对齐 界面角落的版权信息、状态提示
Qt::AlignHCenter | Qt::AlignVCenter 居中对齐(通用) 按钮文本、弹窗标题、居中提示文本
Qt::AlignLeft | Qt::AlignVCenter 左垂直居中 列表项文本、表单标签(左侧文本居中)
Qt::AlignRight | Qt::AlignVCenter 右垂直居中 数值显示(如"金额:100元"的数值部分)
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QtWidgets/QLabel>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this); 

    // ========== 1. label:文本垂直+水平居中 ==========
    // 设置对齐方式:水平居中(HCenter) + 垂直居中(VCenter)
    ui->label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
    // 设置显示文本
    ui->label->setText("垂直水平居中的文本");

    // ========== 2. label_2:左上对齐 + 自动换行 ==========
    // 设置对齐方式:顶部对齐(Top) + 左对齐(Left)
    ui->label_2->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    // 开启自动换行(文本超出label宽度时自动折行)
    ui->label_2->setWordWrap(true);
    // 长文本测试自动换行
    ui->label_2->setText("这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本");

    // ========== 3. label_3:左上对齐 + 首行缩进 ==========
    ui->label_3->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    // 设置首行缩进(缩进20像素)(对所有行都有效)
    ui->label_3->setIndent(20);
    ui->label_3->setWordWrap(true);
    ui->label_3->setText("这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本");

    // ========== 4. label_4:左上对齐 + 内边距 ==========
    ui->label_4->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    // 设置label内部边距(文本与label边框的距离为20像素,四个方向都有效)
    ui->label_4->setMargin(20);
    ui->label_4->setText("这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本这是一个很长的文本");
}
Widget::~Widget()
{
    delete ui; 
}
  • 代码示例4:绑定buddy伙伴
    buddy属性用于将QLabel 标签与一个可聚焦的交互控件(如 QLineEdit、QSpinBox、QPushButton 等)建立 "伙伴关联",按下 QLabel 文本中定义的快捷键(Alt + 字符) 时,键盘焦点会自动跳转到关联的伙伴控件上,无需鼠标点击。
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QLabel>
#include <QLineEdit>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 1. 创建标签(文本含快捷键&U)
    QLabel* label = new QLabel("用户名(&U)", this);
    label->setGeometry(50, 50, 80, 30);

    // 2. 创建输入框
    QLineEdit* edit = new QLineEdit(this);
    edit->setGeometry(140, 50, 200, 30);

    // 3. 设置buddy关联:标签的快捷键指向输入框
    label->setBuddy(edit);
}
Widget::~Widget()
{
    delete ui;
}

结果:无需鼠标点击,按下Alt+U即可输入表单。

4.2 LCDNumber(数字显示)

  • 模拟老式计算器显示效果,支持十进制、十六进制、二进制、八进制显示。
属性名 说明
intValue QLCDNumber 显示的数字值(int类型)。
value QLCDNumber 显示的数字值(double类型),和 intValue 联动(例如value设为1.5时,intValue为2);设置该属性的方法是display,而非setValue/setIntValue
digitCount 显示几位数字。
mode 数字显示形式: 1. QLCDNumber::Dec:十进制(仅该模式可显示小数点内容) 2. QLCDNumber::Hex:十六进制 3. QLCDNumber::Bin:二进制 4. QLCDNumber::Oct:八进制
segmentStyle 设置显示风格: 1. QLCDNumber::Flat:平面风格 2. QLCDNumber::Outline:轮廓风格(带阴影) 3. QLCDNumber::Filled:填充风格(数字与背景区分)
smallDecimalPoint 设置较小的小数点。
  • 代码示例:倒计时功能(使用 QTimer 实现)
  1. 拖放 1 个 LCDNumber(初始值 10);
  2. 编写代码:
cpp 复制代码
// widget.h 声明定时器和更新函数
class Widget : public QWidget
{
    Q_OBJECT
private:
    QTimer* timer;
    void updateTime();
};
// widget.cpp 实现
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    //QTimer是一个类,具有定时器的功能,需要connect绑定timeout信号与槽函数 
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &Widget::updateTime);
    timer->start(1000); // 1秒触发一次
}
void Widget::updateTime()
{
    int value = ui->lcdNumber->intValue();
    if (value <= 0) { timer->stop(); return; }
    ui->lcdNumber->display(value - 1);
}

为什么建议用定时器(QTimer)而不用sleep函数?

Qt的GUI线程(主线程)是基于事件循环工作的:主线程会不断从"事件队列"中取出事件(比如界面绘制、用户点击、定时器触发)并处理,以此保证界面响应和功能运转。

sleep函数的问题在于:

  • 阻塞主线程,中断事件循环 :如果在主线程中调用sleep,主线程会直接暂停(阻塞),事件队列里的事件(界面刷新、用户输入等)完全无法处理 → 界面会卡死、无响应,用户操作没有任何反馈。

QTimer事件驱动式 的:

定时器到期后,会向事件队列中投递一个"定时器事件",主线程会在处理完当前事件后,再处理这个定时器事件------不会阻塞线程,事件循环依然能正常处理其他事件(界面刷新、用户操作),界面始终保持响应。

为什么不能在多线程中sleep?

因为Qt的GUI组件不是线程安全的

  1. GUI组件无线程同步机制:Qt的GUI类(比如QWidget、QLabel等)内部的数据结构(如绘制缓存、控件几何信息)没有加线程锁------多线程并发访问/修改时,会出现"数据竞争",破坏组件的内部状态,导致界面错乱、程序崩溃、行为不可预测。
  2. GUI线程的单线程模型 :Qt规定:只有创建GUI组件的线程(即主线程),才能访问/修改该组件。这是因为GUI的绘制、事件处理都是绑定在主线程的事件循环中的,跨线程操作会脱离这个循环的管控。

Qt中常用前向声明(声明不需要包含头文件,直至定义需要):主要是为了减少头文件依赖:头文件中用前向声明,避免包含过多其他头文件,能加快编译速度(头文件被包含得越少,修改时需要重新编译的文件就越少)。

4.3 ProgressBar(进度条)

  • 显示任务进度,支持水平/垂直方向、进度颜色自定义。
属性名 说明
minimum 进度条最小值
maximum 进度条最大值
value 进度条当前值
alignment 文本在进度条中的对齐方式,包含: - Qt::AlignLeft:左对齐 - Qt::AlignRight:右对齐 - Qt::AlignCenter:居中对齐 - Qt::AlignJustify:两端对齐
textVisible 进度条的数字是否可见
orientation 进度条的方向是水平还是垂直
invertAppearance 是否朝反方向增长进度
textDirection 文本的朝向
format 展示的数字格式,包含: - %p:表示进度的百分比(0-100) - %v:表示进度的数值(0-100) - %m:表示剩余时间(以毫秒为单位) - %t:表示总时间(以毫秒为单位)
  • 代码示例1:进度条自动增长
cpp 复制代码
// widget.h 声明定时器和更新函数
class Widget : public QWidget
{
    Q_OBJECT
private:
    QTimer* timer;
    void updateProgressBar();
};
// widget.cpp 实现
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->progressBar->setRange(0, 100); // 进度范围 0-100
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &Widget::updateProgressBar);
    timer->start(100); // 100ms 触发一次
}
void Widget::updateProgressBar()
{
    int value = ui->progressBar->value();
    if (value >= 100) { timer->stop(); return; }
    ui->progressBar->setValue(value + 1);
}
  • 代码示例2:红色进度条(通过 styleSheet 自定义颜色)
    在 Qt Designer 中选中 ProgressBar,设置 styleSheet:
css 复制代码
QProgressBar::chunk { background-color: #FF0000; }//注意这里需要加上前缀,指定具体控件

4.4 CalendarWidget(日历控件)

属性 说明
selectDate 当前选中的日期
minimumDate 最小日期
maximumDate 最大日期
firstDayOfWeek 每周的第一天(日历第一列)是周几
gridVisible 是否显示表格的边框
selectionMode 是否允许选择日期
navigationBarVisible 日历上方标题是否显示
horizontalHeaderFormat 日历上方标题显示的日期格式
verticalHeaderFormat 日历第一列显示的内容格式
dateEditEnabled 是否允许日期被编辑
  • 显示日历并支持日期选择,核心属性包括 selectDate(选中日期)、minimumDate/maximumDate(日期范围)、gridVisible(是否显示边框)。
  • 信号:selectionChanged(const QDate&)(选中日期变化)、activated(const QDate&)(双击日期)、currentPageChange(int,int)(年份月份改变时发出,形参表示改变后的新年份月份)
  • 代码示例:获取选中的日期
cpp 复制代码
void Widget::on_calendarWidget_selectionChanged()
{
    QDate date = ui->calendarWidget->selectedDate();
    ui->label->setText(date.toString()); // 显示选中日期
}

三、输入类控件

输入类控件用于接收用户输入,常用控件包括 LineEdit(单行输入)、TextEdit(多行输入)、ComboBox(下拉框)、SpinBox(微调框)、DateEdit(日期输入)等。

5.1 LineEdit(单行输入框)

核心属性

属性 说明
text 输入框中的文本
inputMask 输入内容格式约束
maxLength 最大长度
frame 是否添加边框
echoMode 显示方式: QLineEdit::Normal:默认,显示输入文本 QLineEdit::Password:隐藏输入(用*或=代替) QLineEdit::NoEcho:不显示任何输入字符
cursorPosition 光标所在位置
alignment 文字对齐方式,设置水平和垂直方向的对齐
dragEnabled 是否允许拖拽
readOnly 是否是只读的(不允许修改)
placeHolderText 输入框内容为空时显示的提示信息
clearButtonEnabled 是否自动显示"清除按钮"

核心信号

属性 说明
void cursorPositionChanged(int old, int new) 鼠标移动时发出信号,old是原位置,new是新位置
void editingFinished() 按返回/回车键、行编辑失去焦点时发出信号
void returnPressed() 返回/回车键按下时发出信号;若设验证器,需验证通过才触发
void selectionChanged() 选中的文本改变时发出信号
void textChanged(const QString &text) QLineEdit文本改变时发出信号 (代码修改文本也会触发) ,text是新文本
void textEdited(const QString &text) QLineEdit文本改变时发出信号 (代码修改文本不会触发) ,text是新文本
  • 代码示例1:在ui中添加四个label、四个line edit以及两个radiobutton, 个人信息录入(含密码隐藏、手机号格式约束)
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->name->setMaxLength(30);
    ui->name->setClearButtonEnabled(true);
    ui->name->setPlaceholderText("请输入姓名,长度不超过30");

    ui->age->setMaxLength(2);
    ui->age->setClearButtonEnabled(true);
    ui->age->setPlaceholderText("请输入两位数年龄");

    ui->tel->setMaxLength(11);
    ui->tel->setClearButtonEnabled(true);
    ui->tel->setPlaceholderText("请输入电话,你的隐私有我们守护");
    ui->tel->setEchoMode(QLineEdit::Password);
}

void Widget::on_com_but_clicked()
{
    qDebug()<<"你的信息如下:请核实"<<endl;
    qDebug()<<ui->name->text()<<endl;
    qDebug()<<ui->age->text()<<endl;
    if(ui->boy_but->isChecked()) qDebug()<<"boy"<<endl;
    else qDebug()<<"girl"<<endl;
    qDebug()<<ui->tel->text()<<endl;
}

如何快速准确地判断表单内数据是否合法?

  1. 采用inputMask进行验证,但是其功能具有局限性。
cpp 复制代码
ui->tel->setInputMask("10000000000");//代表开头为1,其余必须输入10个0-9之间的数
  1. 采用正则表达式验证器:
    正则表达式(Regular Expression,Regex/RegExp),它是一种通用的文本处理工具,可以:
  • 验证格式:判断字符串是否符合特定规则(比如手机号、邮箱、密码是否合法);
  • 查找内容:从文本中快速提取符合规则的片段;
  • 替换文本:批量替换符合规则的文本内容。

Qt提供了专门的类来实现"输入框内容必须符合正则规则"的功能,核心是 QRegularExpressionValidator (Qt5及以上推荐,替代旧的QRegExpValidator),它通常和QLineEdit(输入框)配合使用,强制限制输入内容的格式。

cpp 复制代码
State validate(QString &input, int &pos);
  • 返回值 State:

    返回 QValidator::State 枚举 (Acceptable/Intermediate/Invalid),表示输入内容的验证状态:

    • Acceptable:内容完全符合规则;
    • Intermediate:内容部分符合(比如手机号输入了 5 位数字,还没填完);
    • Invalid:内容完全不符合(比如手机号输入了字母)。
  • 参数 QString &input(引用传递):

    传入要验证的输入字符串,同时支持验证器修改输入内容(比如自动去除空格、补全格式)。

  • 参数 int &pos(引用传递):

    传入当前光标在输入框中的位置,同时支持验证器调整光标位置(比如用户输入非法字符后,将光标定位到错误位置)。不常用就是了~

  • 代码示例2:正则表达式验证手机号(11位数字)

cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->pushButton->setEnabled(false); // 初始禁用确定按钮
    // 正则表达式:以1开头,后续10位数字
	// 1. 定义手机号正则表达式规则(QRegExp是Qt旧版正则类,Qt5+推荐用			QRegularExpression)
	// 正则规则解析:
	// ^   :匹配字符串开头
	// 1   :手机号必须以数字1开头
	// \\d :匹配任意数字(\d在C++字符串中需转义为\\d)
	// {10}:表示前面的\d重复10次,加上开头的1总共11位数字
	// $   :匹配字符串结尾
	QRegExp telregex("^1\\d{10}$");
	// 2. 给界面上的tel输入框(QLineEdit)设置正则验证器
	// QRegExpValidator:基于QRegExp的验证器,用于约束输入框内容格式
	// 绑定后,tel输入框会自动过滤不符合"1开头11位数字"规则的输入
    ui->tel->setValidator(new QRegExpValidator(telregex));
}
// 文本变化时验证(testedit请看上面的槽函数介绍)
void Widget::on_lineEdit_textEdited(const QString &arg1)
{
    QString content = arg1;
    int pos = 0;
    // 验证通过则启用按钮
    // validate():验证器的核心方法,返回验证状态(Acceptable/Intermediate/Invalid)
	// QValidator::Acceptable:表示内容完全符合验证规则(合法)
    if (ui->lineEdit->validator()->validate(content, pos) == QValidator::Acceptable) {
        ui->pushButton->setEnabled(true);
    } else {
        ui->pushButton->setEnabled(false);
    }
}
  • 代码实例3:切换显示密码
cpp 复制代码
//参数为按钮状态改变后的新状态
void Widget::on_checkBox_toggled(bool checked)
{
    if(checked==true) ui->tel->setEchoMode(QLineEdit::Normal);
    else ui->tel->setEchoMode(QLineEdit::Password);
}

5.2 TextEdit(多行输入框)

核心属性

属性 说明
markdown 输入框内持有的内容,支持markdown格式,能够自动对markdown文本进行渲染成html
html 输入框内持有的内容,可以支持大部分html标签,包括img和table等
placeHolderText 输入框为空时提示的内容
readOnly 是否是只读的
undoRedoEnable 是否开启undo/redo功能: 按下ctrl+z触发undo 按下ctrl+y触发redo
autoFormatting 开启自动格式化
tabstopWidth 按下缩进进多少空间
overwriteMode 是否开启覆盖写模式
acceptRichText 是否接收富文本内容
verticalScrollBarPolicy 垂直方向滚动条的出现策略 Qt::ScrollBarAsNeeded:根据内容自动决定(默认) Qt::ScrollBarAlwaysOff:总是关闭 Qt::ScrollBarAlwaysOn:总是显示
horizontalScrollBarPolicy 水平方向滚动条的出现策略 Qt::ScrollBarAsNeeded:根据内容自动决定(默认) Qt::ScrollBarAlwaysOff:总是关闭 Qt::ScrollBarAlwaysOn:总是显示

核心信号

信号 说明
textChanged() 文本内容改变时触发
selectionChanged() 选中范围改变时触发
cursorPositionChanged() 光标移动时触发
undoAvailable(bool) 可以进行undo操作时触发
redoAvailable(bool) 可以进行redo操作时触发
copyAvailable(bool) 文本被选中/取消选中时触发
  • 相比于LineEdit,TextEdit支持多行文本输入 ,可作为富文本/Markdown 编辑器,自动显示滚动条。
  • 核心属性:markdown/html(支持 Markdown/HTML 格式)、readOnly(只读)、undoRedoEnable(支持撤销/重做)。
  • 代码示例1:实时获取输入内容
cpp 复制代码
void Widget::on_textEdit_textChanged()
{
    const QString& content = ui->textEdit->toPlainText();//注意这里获取文本的函数需要to
    ui->label->setText(content); 
}
  • 代码示例2:验证各种信号函数
cpp 复制代码
void Widget::on_textEdit_1_textChanged()
{
    //文本发生改变
    qDebug() << "[textChanged] " << ui->textEdit_1->toPlainText();
}

void Widget::on_textEdit_1_selectionChanged()
{
    //选中范围发生改变
    const QTextCursor& cursor = ui->textEdit_1->textCursor();
     qDebug() << "[selectionChanged] " << cursor.selectedText();
}

void Widget::on_textEdit_1_cursorPositionChanged()
{
    //光标发生改变
    const QTextCursor& cursor = ui->textEdit_1->textCursor();
    qDebug() << "[cursorPositionChanged] " << cursor.position();
}

void Widget::on_textEdit_1_redoAvailable(bool b)
{
    //是否可以进行redo恢复操作(ctrl+Z)
    qDebug() << "[redoAvailable] " << b;
}

void Widget::on_textEdit_1_undoAvailable(bool b)
{
    //是否可以进行undo撤销操作(ctrl+Y)
    qDebug() << "[undoAvailable] " << b;
}

void Widget::on_textEdit_1_copyAvailable(bool b)
{
    //选中内容后进行是都开可以进行copy操作
    qDebug() << "[copyAvailable] " << b;
}

5.3 ComboBox(下拉框)

核心属性

属性 说明
currentText 当前选中的文本
currentIndex 当前选中的条目下标(从0开始计算;无选中时为-1)
editable 是否允许修改:设为true时,行为接近QLineEdit,可设置validator
iconSize 下拉框图标(小三角)的大小
maxCount 最多允许的条目数量

核心方法

方法 说明
addItem(const QString&) 添加一个条目
currentIndex() 获取当前条目的下标(从0开始计算;无选中时为-1)
currentText() 获取当前条目的文本内容

核心信号

方法 说明
activated(int) 当用户选择一个选项时发出
activated(const QString &text) 用户点开下拉框、鼠标划过选项时发出(未确认选择)
currentIndexChanged(int) 当前选项改变时发出(用户已明确选择)
currentIndexChanged(const QString &text) 当前选项改变时发出(用户/程序操作都会触发)
editTextChanged(const QString &text) 编辑框中文本改变时发出(仅editable为true时有效)
  • 代码示例1:选择出生日期
    • 可以使用ui添加:

    • 也可以使用代码添加

cpp 复制代码
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    for(int i=0;i<100;++i) ui->year->addItem(QString::number(1999 + i));
    for(int i=0;i<12;i++)  ui->month->addItem(QString::number(i+1));
    for(int i=0;i<30;i++)  ui->day->addItem(QString::number(i+1));
}
  • 代码示例2:从文件加载下拉框选项
cpp 复制代码
#include <fstream>
Widget::Widget(QWidget *parent)
: QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 读取 d:/config.txt 中的选项(每行一个选项)
    std::ifstream file("d:/config.txt");
    std::string line;
    while (std::getline(file, line)) {
        ui->comboBox->addItem(QString::fromStdString(line));
        //fromStdString是string转为QString的关键函数
    }
    file.close();
}

5.4 SpinBox(微调框)

使用 QSpinBoxQDoubleSpinBox 表示"微调框",是带按钮的输入框,用于输入整数/浮点数,可通过点击按钮修改数值。(SpinBoxQDoubleSpinBox 用法基本一致,以下仅介绍 SpinBox

关键属性

属性名 说明
value 存储的数值
singleStep 每次调整的"步长"(按下一次按钮的数值变化量)
displayInteger 数字进制(例:设为10则十进制,设为2则二进制)
minimum 最小值
maximum 最大值
suffix 后缀
prefix 前缀
wrapping 是否允许换行
frame 是否带边框
alignment 文字对齐方式
readOnly 是否允许修改
buttonSymbol 按钮图标样式: - UpDownArrows(上下箭头) - PlusMinus(加减号) - NoButtons(无按钮)
accelerated 按下按钮时是否开启快速调整模式
correctionMode 输入错误时的修正规则: - CorrectToPreviousValue(恢复上一个有效值) - CorrectToNearestValue(恢复最接近的有效值)
keyboardTrack 键盘跟踪开关: - true:输入数字时实时触发信号 - false:仅按下Enter/失去焦点时触发信号

核心信号

信号名 说明
textChanged(QString) 微调框文本变化时触发(参数包含前缀/后缀)
valueChanged(int) 微调框数值变化时触发(参数为当前数值)
  • 代码示例1:麦当劳点单页面
    • 3个下拉框:objectNamecomboBox/comboBox_2/comboBox_3
    • 3个微调框:objectNamespinBox/spinBox_2/spinBox_3
    • 1个按钮:objectNamepushButton
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
   , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 初始化下拉框
    ui->comboBox->addItem("巨无霸");
    ui->comboBox->addItem("麦辣鸡腿");
    ui->comboBox_2->addItem("薯条");
    ui->comboBox_2->addItem("麦辣鸡翅");
    ui->comboBox_3->addItem("可乐");
    ui->comboBox_3->addItem("雪碧");

    // 初始化微调框(默认值1,范围1~5)
    ui->spinBox->setValue(1);
    ui->spinBox->setRange(1, 5);
    ui->spinBox_2->setValue(1);
    ui->spinBox_2->setRange(1, 5);
    ui->spinBox_3->setValue(1);
    ui->spinBox_3->setRange(1, 5);
}
void Widget::on_pushButton_clicked()
{
    qDebug() << "当前下单的内容:"
             << ui->comboBox->currentText() << ":" << ui->spinBox->value()
             << ui->comboBox_2->currentText() << ":" << ui->spinBox_2->value()
             << ui->comboBox_3->currentText() << ":" << ui->spinBox_3->value();
}

5.5 Date Edit & Time Edit (日期/时间)

  • QDateEdit:日期微调框(示例样式:2000/1/1
  • QTimeEdit:时间微调框(示例样式:0:00
  • QDateTimeEdit:日期时间微调框(示例样式:2000/1/1 0:00

QDateTimeEdit 核心属性

属性名 说明
dateTime 时间日期值(示例:2000/1/1 0:00:00
date 单纯日期值(示例:2000/1/1
time 单纯时间值(示例:0:00:00
displayFormat 时间日期格式(示例:yyyy/M/d H:m:s),格式符含义: - y:年份 - M:月份 - d:日期 - H:小时 - m:分钟 - s:秒 ⚠️ 注意:格式符规则因语言/库有差异,使用时需查阅文档
minimumDateTime 最小时间日期
maximumDateTime 最大时间日期
timeSpec 时间标准: - Qt::LocalTime:显示本地时间 - Qt::UTC:显示协调世界时(UTC) - Qt::OffsetFromUTC:显示相对于UTC的偏移量(时差)
  • UTC:基于原子钟的标准时间,不受地球自转影响(与格林威治时间GMT接近,由科学家维护);计算机内部时间基于UTC。
  • 本地时间:基于时区对UTC的调整(例如北京时间为东八区,需在UTC基础上加8小时)。

核心信号

信号名 说明
dateChanged(QDate) 日期改变时触发
timeChanged(QTime) 时间改变时触发
dateTimeChanged(QDateTime) 时间/日期任意一个改变时触发
  • 代码示例1:日期差计算器

  • 2个 QDateTimeEditobjectNamedateTimeEdit_olddateTimeEdit_new

  • 1个按钮、1个 label(用于显示结果)

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    //这里用于计算日期差
    QDateTime timeOld = ui->date_1->dateTime();
    QDateTime timeNew=ui->date_2->dateTime();
    
    int days=timeOld.daysTo(timeNew),seconds=timeOld.secsTo(timeNew);
    int hours=(seconds-days*24*60*60)/3600;
    
    ui->pushButton->setText("日期差:"+QString::fromStdString(std::to_string(days)+"天,"+std::to_string(hours)+"小时"));
}

由于 daysTo 仅计算两个 QDateTime 的 "日期部分" 的差值(忽略小时、分钟、秒),即使不满24小时但跨日期就会发生错误,这里建议使用seconds来计算天与小时。

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    //这里用于计算日期差
    QDateTime timeOld = ui->date_1->dateTime();
    QDateTime timeNew=ui->date_2->dateTime();
    int seconds=timeOld.secsTo(timeNew);
    int days=seconds/(24*60*60);
    int hours=(seconds-days*24*60*60)/3600;
    ui->pushButton->setText("日期差:"+QString::fromStdString(std::to_string(days)+"天,"+std::to_string(hours)+"小时"));
}

5.6 Dial(旋钮)

使用 QDial 表示一个旋钮,可通过鼠标拖动旋转实现参数设置。

核心属性

属性名 说明
value 旋钮持有的数值
minimum 数值最小值
maximum 数值最大值
singleStep 按下方向键时的数值步长
pageStep 按下PageUp/PageDown时的数值步长
sliderPosition 旋钮在界面上的初始显示位置
tracking 外观是否跟踪数值变化(默认true,一般无需修改)
wrapping 是否允许循环调整(数值超过最大值时是否回滚到最小值,即"套圈"效果)
notchesVisible 是否显示刻度线
notchTarget 刻度线的相对位置(数值越大,刻度线越稀疏)

核心信号

信号名 说明
valueChanged(int) 数值改变时触发
rangeChanged(int, int) 数值范围变化时触发
  • 代码示例1:调整窗口透明度

  • 1个 QDial(旋钮)

  • 1个 label(显示当前透明度)

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
   , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 允许循环旋转
    ui->dial->setWrapping(true);
    // 显示刻度线
    ui->dial->setNotchesVisible(true);
    // 设置数值范围(0~100,对应透明度0~100%)
    ui->dial->setMaximum(100);
    ui->dial->setMinimum(0);
    // 初始值设为100(完全不透明)
    ui->dial->setValue(100);
}

void Widget::on_dial_valueChanged(int value)
{
    // 设置窗口透明度(范围0.0~1.0)
    this->setWindowOpacity((double)value / 100);
}

5.7 Slider(滑动条)

使用 QSlider 表示一个滑动条 ,与 QDial 均继承自 QAbstractSlider,用法基本相同。

核心属性

属性名 说明
value 滑动条持有的数值
minimum 数值最小值
maximum 数值最大值
singleStep 按下方向键时的数值步长
pageStep 按下PageUp/PageDown时的数值步长
sliderPosition 滑动条的初始显示位置
tracking 外观是否跟踪数值变化(默认true,一般无需修改)
orientation 滑动条方向(水平/垂直)
invertedAppearance 是否翻转滑动条的方向 (默认从左向右增长,从下到上增长)
tickPosition 刻度的显示位置
tickInterval 刻度的密集程度

核心信号

信号名 说明
valueChanged(int) 数值改变时触发
rangeChanged(int, int) 数值范围变化时触发
  • 代码示例1:调整窗口大小

  • 2个滑动条:objectNamehorizontalSlider(水平)、verticalSlider(垂直)

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent) 
   , ui(new Ui::Widget)  
{
    ui->setupUi(this); 
    ui->horizontalSlider->setMinimum(500);    // 设置最小值:500
    ui->horizontalSlider->setMaximum(2000);   // 设置最大值:2000
    ui->horizontalSlider->setSingleStep(100); // 设置步长:每次调整变化100
    ui->horizontalSlider->setValue(800);      // 设置初始值:800
    
    ui->verticalSlider->setMinimum(500);      // 设置最小值:500
    ui->verticalSlider->setMaximum(1500);     // 设置最大值:1500
    ui->verticalSlider->setSingleStep(100);   // 设置步长:每次调整变化100
    ui->verticalSlider->setValue(600);        // 设置初始值:600
    // 翻转滑动条方向:默认滑块是"从下往上增长",改为"从上往下增长"
    ui->verticalSlider->setInvertedAppearance(true);
}

void Widget::on_horizontalSlider_valueChanged(int value)
{
    QRect rect=this->geometry();
    this->setGeometry(rect.x(),rect.y(),value,rect.height());
}


void Widget::on_verticalSlider_valueChanged(int value)
{
    QRect rect=this->geometry();
    this->setGeometry(rect.x(),rect.y(),rect.width(),value);
}
  • 代码示例2:通过⾃定义快捷键调整滑动条位置
  • 编写两个QShortCut类,进行快捷键的设置
cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)  // 调用父类QWidget的构造函数
   , ui(new Ui::Widget)  // 初始化UI对象
{
    ui->setupUi(this);  // 加载UI界面
    
	QShortcut* cut1=new QShortcut(this),*cut2=new QShortcut(this);
    cut1->setKey(QKeySequence(Qt::Key_Left));
    cut2->setKey(QKeySequence(Qt::Key_Right));
    connect(cut1,&QShortcut::activated,this,&Widget::left);
    connect(cut2,&QShortcut::activated,this,&Widget::right);
}

void Widget::left()
{
    int value=ui->horizontalSlider->value();
    ui->horizontalSlider->setValue(value-20);
}
void Widget::right()
{
    int value=ui->horizontalSlider->value();
    ui->horizontalSlider->setValue(value+20);
}
相关推荐
一条大祥脚13 小时前
26.1.9 轮廓线dp 状压最短路 构造
数据结构·c++·算法
Mr -老鬼13 小时前
前端静态路由与动态路由:全维度总结与实践指南
前端
项目題供诗14 小时前
C语言基础(一)
c++
颜酱14 小时前
前端必备动态规划的10道经典题目
前端·后端·算法
wen__xvn14 小时前
代码随想录算法训练营DAY10第五章 栈与队列part01
java·前端·算法
@areok@15 小时前
C++opencv图片(mat)传入C#bitmap图片
开发语言·c++·opencv
鸽芷咕15 小时前
【2025年度总结】时光知味,三载同行:落笔皆是沉淀,前行自有光芒
linux·c++·人工智能·2025年度总结
羑悻的小杀马特15 小时前
指尖敲代码,笔尖写成长:2025年度总结与那些没说出口的碎碎念
linux·c++·博客之星·2025年度总结
linweidong15 小时前
C++thread pool(线程池)设计应关注哪些扩展性问题?
java·数据库·c++