目录
[二、LineEdit:单行输入的 "万能选手"](#二、LineEdit:单行输入的 “万能选手”)
[2.1 核心属性与 API](#2.1 核心属性与 API)
[2.2 基础用法:快速实现常见输入场景](#2.2 基础用法:快速实现常见输入场景)
[2.2.1 普通文本输入(账号 / 昵称)](#2.2.1 普通文本输入(账号 / 昵称))
[2.2.2 固定格式输入(手机号 / 身份证号)](#2.2.2 固定格式输入(手机号 / 身份证号))
[2.3 实战案例 1:正则表达式验证](#2.3 实战案例 1:正则表达式验证)
[2.4 实战案例 2:密码一致性校验(两次输入密码一致)](#2.4 实战案例 2:密码一致性校验(两次输入密码一致))
[2.5 实战案例 3:密码显示 / 隐藏切换](#2.5 实战案例 3:密码显示 / 隐藏切换)
[2.6 LineEdit 避坑指南](#2.6 LineEdit 避坑指南)
[问题 1:输入中文时textEdited信号不触发?](#问题 1:输入中文时textEdited信号不触发?)
[问题 2:正则验证器不生效,仍能输入非法字符?](#问题 2:正则验证器不生效,仍能输入非法字符?)
[问题 3:inputMask与validator同时使用时冲突?](#问题 3:inputMask与validator同时使用时冲突?)
[三、TextEdit:多行富文本的 "全能编辑器"](#三、TextEdit:多行富文本的 “全能编辑器”)
[3.1 核心属性与 API](#3.1 核心属性与 API)
[3.2 基础用法:纯文本与富文本输入](#3.2 基础用法:纯文本与富文本输入)
[3.2.1 普通多行文本输入](#3.2.1 普通多行文本输入)
[3.2.2 富文本与 Markdown 渲染](#3.2.2 富文本与 Markdown 渲染)
[3.3 TextEdit 避坑指南](#3.3 TextEdit 避坑指南)
[问题 1:Markdown 格式不生效?](#问题 1:Markdown 格式不生效?)
[问题 2:TextEdit 自动换行后,光标位置计算错误?](#问题 2:TextEdit 自动换行后,光标位置计算错误?)
[问题 3:插入图片后,程序打包后图片丢失?](#问题 3:插入图片后,程序打包后图片丢失?)
[四、ComboBox:下拉选择的 "高效控件"](#四、ComboBox:下拉选择的 “高效控件”)
[4.1 核心属性与 API](#4.1 核心属性与 API)
[4.2 基础用法:固定选项与可编辑模式](#4.2 基础用法:固定选项与可编辑模式)
[4.2.1 固定选项下拉框(分类选择)](#4.2.1 固定选项下拉框(分类选择))
[4.2.2 可编辑下拉框(支持输入 + 选择)](#4.2.2 可编辑下拉框(支持输入 + 选择))
[4.3 实战案例:从文件加载下拉选项](#4.3 实战案例:从文件加载下拉选项)
[4.4 ComboBox 避坑指南](#4.4 ComboBox 避坑指南)
[问题 1:添加选项后,currentIndex始终为 - 1?](#问题 1:添加选项后,currentIndex始终为 - 1?)
[问题 2:可编辑模式下,输入的文本不会添加到选项列表?](#问题 2:可编辑模式下,输入的文本不会添加到选项列表?)
[问题 3:从文件加载选项时,中文乱码?](#问题 3:从文件加载选项时,中文乱码?)
[五、SpinBox/DoubleSpinBox:数值微调的 "精准工具"](#五、SpinBox/DoubleSpinBox:数值微调的 “精准工具”)
[5.1 核心属性与 API](#5.1 核心属性与 API)
[5.2 基础用法:微调数字](#5.2 基础用法:微调数字)
[5.3 SpinBox 避坑指南](#5.3 SpinBox 避坑指南)
[问题 1:DoubleSpinBox 显示多位小数,精度丢失?](#问题 1:DoubleSpinBox 显示多位小数,精度丢失?)
[问题 2:设置wrapping=true后,数值超过最大值不循环?](#问题 2:设置wrapping=true后,数值超过最大值不循环?)
[问题 3:输入非法数值(如字母)后,数值不变?](#问题 3:输入非法数值(如字母)后,数值不变?)
[六、DateEdit/TimeEdit/DateTimeEdit:日期时间的 "标准输入"](#六、DateEdit/TimeEdit/DateTimeEdit:日期时间的 “标准输入”)
[6.1 核心属性与 API](#6.1 核心属性与 API)
[6.2 日期计算器(计算两个日期的天数差)](#6.2 日期计算器(计算两个日期的天数差))
[6.3 日期时间控件避坑指南](#6.3 日期时间控件避坑指南)
[问题 1:显示格式不生效(如 "yyyy-MM-dd" 显示为 "2025/01/01")?](#问题 1:显示格式不生效(如 “yyyy-MM-dd” 显示为 “2025/01/01”)?)
[问题 2:日历弹窗不显示?](#问题 2:日历弹窗不显示?)
[问题 3:设置minimumDate后,仍能手动输入过去的日期?](#问题 3:设置minimumDate后,仍能手动输入过去的日期?)
[7.1 核心属性与 API](#7.1 核心属性与 API)
[7.2 基础用法:旋钮调节](#7.2 基础用法:旋钮调节)
[7.3 实战案例:旋钮调节窗口透明度](#7.3 实战案例:旋钮调节窗口透明度)
[7.4 Dial 避坑指南](#7.4 Dial 避坑指南)
[问题 1:旋钮旋转时,数值变化不流畅?](#问题 1:旋钮旋转时,数值变化不流畅?)
[问题 2:wrapping=true后,旋转到最大值不循环?](#问题 2:wrapping=true后,旋转到最大值不循环?)
[问题 3:刻度线不显示?](#问题 3:刻度线不显示?)
[8.1 核心属性与 API](#8.1 核心属性与 API)
[8.2 通过滑动条调节窗口大小](#8.2 通过滑动条调节窗口大小)
[8.3 快捷键控制滑动条](#8.3 快捷键控制滑动条)
[8.5 Slider 避坑指南](#8.5 Slider 避坑指南)
[问题 1:滑动条拖动时,数值变化滞后?](#问题 1:滑动条拖动时,数值变化滞后?)
[问题 2:垂直滑动条调节方向与预期相反?](#问题 2:垂直滑动条调节方向与预期相反?)
[问题 3:刻度线不显示?](#问题 3:刻度线不显示?)
前言
在 Qt GUI 开发中,输入类控件是用户与程序交互的核心桥梁 ------ 无论是简单的账号密码输入,还是复杂的长文本编辑、日期选择,都离不开输入类控件的支持。Qt 内置了 7 种高频输入类控件,从单行输入框(LineEdit)到旋钮(Dial)、滑动条(Slider),覆盖了几乎所有输入场景。本文将基于 Qt 5.14 版本,以 "属性解析 + 基础用法 + 实战案例 + 避坑指南" 的结构,全面拆解每个控件的核心用法,带你从零掌握输入类控件的开发技巧!下面就让我么正式开始吧!
一、输入类控件的核心价值
输入类控件是程序 "接收用户指令" 的关键载体,其设计直接影响用户体验:一个支持格式验证的 LineEdit 能减少用户输入错误,一个灵活的 Slider 能让数值调节更直观,一个带范围限制的 DateEdit 能避免非法日期输入。
本文将重点讲解以下 7 种输入类控件:
- LineEdit:单行文本输入(账号、密码、手机号等)
- TextEdit:多行富文本输入(评论、笔记、文档等)
- ComboBox:下拉选项选择(分类筛选、菜单选择等)
- SpinBox/DoubleSpinBox:数值微调(数量、参数调节等)
- DateEdit/TimeEdit/DateTimeEdit:日期时间输入(预约、日程等)
- Dial:旋钮调节(音量、亮度、透明度等)
- Slider:滑动条调节(进度、大小、强度等)
在本文中,每个控件均搭配完整 C++ 代码示例,兼顾入门学习与实战开发,读完本文你将能轻松实现各类输入交互场景。
二、LineEdit:单行输入的 "万能选手"
QLineEdit 是 Qt 中最常用的单行输入控件,支持密码隐藏、格式验证、占位提示等核心功能,适用于账号、密码、手机号、邮箱等单行输入场景。
2.1 核心属性与 API
LineEdit 的核心属性围绕 "输入约束" 和 "显示效果" 展开,常用属性与 API 如下:
| 属性名 | 功能说明 | 实用场景 |
|---|---|---|
| text | 获取 / 设置输入框文本 | 所有单行输入场景 |
| echoMode | 文本显示模式(Normal/Password/NoEcho) | 密码输入(Password 模式)、隐私输入(NoEcho 模式) |
| placeholderText | 空输入时的提示文本 | 引导用户输入(如 "请输入手机号") |
| maxLength | 最大输入长度限制 | 手机号(11 位)、验证码(6 位)等 |
| clearButtonEnabled | 显示 "清除按钮"(输入后显示 ×) | 快速清空输入内容 |
| inputMask | 输入格式约束(如 "000-0000-0000") | 手机号、身份证号等固定格式输入 |
| readOnly | 设置只读(禁止修改) | 展示不可编辑的文本(如已确认的订单号) |
| focusPolicy | 焦点获取策略(Tab/Click/StrongFocus) | 表单输入时的焦点切换 |
核心 API:
- text():获取输入文本
- setText(const QString& text):设置输入文本
- clear():清空输入内容
- setValidator(QValidator v)*:设置输入验证器(正则、数值范围等)
- returnPressed():按下回车键时触发的信号
2.2 基础用法:快速实现常见输入场景
2.2.1 普通文本输入(账号 / 昵称)
首先在.ui界面加入控件:

cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//初始化第一个输入框,用来输入姓名
ui->lineEdit_name->setPlaceholderText("请输入姓名");
ui->lineEdit_name->setClearButtonEnabled(true);
//初始化第二个输入框,用于输入密码
ui->lineEdit_password->setPlaceholderText("请输入密码");
ui->lineEdit_password->setClearButtonEnabled(true);
//把显示模式设置为显示密码的格式
ui->lineEdit_password->setEchoMode(QLineEdit::Password);
//初始化第三个输入框
ui->lineEdit_phone->setPlaceholderText("请输入电话号码");
ui->lineEdit_phone->setClearButtonEnabled(true);
//手机号码输入有固定格式,此处的0代表数字
ui->lineEdit_phone->setInputMask("000-0000-0000");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_submit_clicked()
{
QString gender = ui->radioButton_male->isChecked() ? "男" : "女";
qDebug() << "姓名:" << ui->lineEdit_name->text()
<< "密码:" << ui->lineEdit_password->text()
<< "性别:" << gender
<< "电话:" << ui->lineEdit_phone->text();
}
运行结果:

2.2.2 固定格式输入(手机号 / 身份证号)
使用inputMask属性可约束输入格式,无需手动验证固定位数的分隔符:
cpp
// 手机号输入框(格式:000-0000-0000)
QLabel *phoneLabel = new QLabel("手机号:", this);
QLineEdit *phoneEdit = new QLineEdit(this);
phoneEdit->setInputMask("000-0000-0000"); // 0表示必须输入数字
phoneEdit->setPlaceholderText("请输入手机号");
layout->addWidget(phoneLabel);
layout->addWidget(phoneEdit);
// 身份证号输入框(格式:000000-00000000-0000-00)
QLabel *idLabel = new QLabel("身份证号:", this);
QLineEdit *idEdit = new QLineEdit(this);
idEdit->setInputMask("000000-00000000-0000-00");
layout->addWidget(idLabel);
layout->addWidget(idEdit);
2.3 实战案例 1:正则表达式验证
inputMask仅能约束格式,无法验证内容合法性(如手机号必须以 1 开头)。使用**正则表达式验证器(QRegExpValidator)**可实现更严格的输入校验:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QRegExpValidator>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//需要给单行输入框设置验证器,基于正则表达式来完成验证
QRegExp regExp("^1\\d{10}$");
ui->lineEdit->setValidator(new QRegExpValidator(regExp));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_lineEdit_textEdited(const QString &text)
{
QString content = text;
int pos = 0;
if(ui->lineEdit->validator()->validate(content, pos))
{
//验证通过
ui->pushButton->setEnabled(true);
}
else
{
//验证不通过
ui->pushButton->setEnabled(false);
}
}
运行结果如下:

关键技术点:
- 正则表达式**^1\d{10}**:`^`表示开头,`1`表示首字符为 1,`\\d{10}`表示 10 位数字,``表示结尾;
- QRegExpValidator:Qt 内置的正则验证器,通过
validate方法返回验证结果(Acceptable/Intermediate/Invalid);- textEdited信号:仅当用户手动输入文本时触发(代码修改文本不触发),适合实时验证场景。
2.4 实战案例 2:密码一致性校验(两次输入密码一致)
在注册界面中,常需要验证两次输入的密码是否一致,结合两个 LineEdit 和 Label 实现实时提示:
首先还是先打开.ui文件,设置两个LineEdit:

编辑widget.cpp文件如下:
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//初始化,把这两个输入框的echoMode设置一下
ui->lineEdit->setEchoMode(QLineEdit::Password);
ui->lineEdit_2->setEchoMode(QLineEdit::Password);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_lineEdit_textEdited(const QString &arg1)
{
(void) arg1;
const QString& s1 = ui->lineEdit->text();
const QString& s2 = ui->lineEdit_2->text();
if(s1.isEmpty() && s2.isEmpty())
{
ui->label->setText("密码为空");
}
else if(s1 == s2)
{
ui->label->setText("两次输入的密码一致");
}
else
{
ui->label->setText("两次输入的密码不一致");
}
}
void Widget::on_lineEdit_2_textEdited(const QString &arg1)
{
(void) arg1;
const QString& s1 = ui->lineEdit->text();
const QString& s2 = ui->lineEdit_2->text();
if(s1.isEmpty() && s2.isEmpty())
{
ui->label->setText("密码为空");
}
else if(s1 == s2)
{
ui->label->setText("两次输入的密码一致");
}
else
{
ui->label->setText("两次输入的密码不一致");
}
}
运行结果:


2.5 实战案例 3:密码显示 / 隐藏切换
通过复选框控制密码输入框的echoMode属性,实现密码显示与隐藏的切换:
cpp
#include "widget.h"
#include <QLineEdit>
#include <QLabel>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("密码显示/隐藏切换");
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// 密码输入框
QLabel *pwdLabel = new QLabel("密码:", this);
QLineEdit *pwdEdit = new QLineEdit(this);
pwdEdit->setEchoMode(QLineEdit::Password);
pwdEdit->setPlaceholderText("请输入密码");
// 复选框(显示密码)
QCheckBox *showPwdBox = new QCheckBox("显示密码", this);
// 布局:复选框靠右
QHBoxLayout *pwdLayout = new QHBoxLayout();
pwdLayout->addWidget(pwdLabel);
pwdLayout->addWidget(pwdEdit);
pwdLayout->addWidget(showPwdBox);
mainLayout->addLayout(pwdLayout);
// 复选框状态变化时切换echoMode
connect(showPwdBox, &QCheckBox::toggled, this, [=](bool checked) {
if (checked) {
pwdEdit->setEchoMode(QLineEdit::Normal); // 显示明文
} else {
pwdEdit->setEchoMode(QLineEdit::Password); // 隐藏为星号
}
});
}
2.6 LineEdit 避坑指南
问题 1:输入中文时textEdited信号不触发?
- 原因:textEdited仅在用户输入单个字符时触发,中文输入过程中(未确认输入前)不会触发;
- 解决方案:使用textChanged信号(任何文本变化都触发),或结合
editingFinished(输入完成后触发)。
问题 2:正则验证器不生效,仍能输入非法字符?
- 原因:QRegExpValidator默认允许 "中间状态"(如输入过程中的不完整文本),仅阻止完全非法的字符;
- 解决方案:设置验证器为 "严格模式",或在
returnPressed时再次校验。
问题 3:inputMask与validator同时使用时冲突?
- 原因:两者都用于输入约束,inputMask优先级更高;
- 解决方案:根据场景选择其一,固定格式用inputMask,复杂内容验证用validator。
三、TextEdit:多行富文本的 "全能编辑器"
QTextEdit是支持多行输入的富文本编辑器,不仅能输入普通文本,还支持 Markdown、HTML 格式渲染,自带滚动条,适用于评论、笔记、文档编辑等场景。
3.1 核心属性与 API
TextEdit 的核心属性围绕 "文本格式" 和 "编辑行为" 展开:
| 属性名 | 功能说明 | 实用场景 |
|---|---|---|
| markdown | 获取 / 设置 Markdown 格式文本 | Markdown 笔记、文档编辑 |
| html | 获取 / 设置 HTML 格式文本 | 富文本展示(图片、表格、样式) |
| plainText | 获取 / 设置纯文本 | 普通多行输入 |
| placeholderText | 空输入时的提示文本 | 引导用户输入(如 "请输入评论内容") |
| readOnly | 设置只读 | 展示不可编辑的富文本(如帮助文档) |
| undoRedoEnabled | 启用撤销 / 重做(Ctrl+Z/Ctrl+Y) | 文本编辑场景 |
| acceptRichText | 是否接收富文本 | 仅允许纯文本时设为 false |
| verticalScrollBarPolicy | 垂直滚动条策略(AsNeeded/AlwaysOn/AlwaysOff) | 控制滚动条显示时机 |
核心 API:
- toPlainText():获取纯文本
- toMarkdown():获取 Markdown 格式文本
- toHtml():获取 HTML 格式文本
- setPlainText(const QString& text):设置纯文本
- append(const QString& text):追加文本(自动换行)
- clear():清空文本
3.2 基础用法:纯文本与富文本输入
3.2.1 普通多行文本输入
先在.ui文件中配置Label和TextEdit控件:

编写代码:
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_textEdit_textChanged()
{
//获取到多行输入框中的内容
const QString& text = ui->textEdit->toPlainText();
ui->label->setText(text);
}
运行结果:

3.2.2 富文本与 Markdown 渲染
TextEdit 支持直接解析 HTML 和 Markdown 格式,无需额外插件:
cpp
#include "widget.h"
#include <QTextEdit>
#include <QTabWidget>
#include <QVBoxLayout>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("TextEdit富文本支持");
QVBoxLayout *layout = new QVBoxLayout(this);
// 标签页:分别展示HTML和Markdown
QTabWidget *tabWidget = new QTabWidget(this);
// HTML标签页
QTextEdit *htmlEdit = new QTextEdit(this);
htmlEdit->setReadOnly(true);
QString htmlText = QString("<h2 style='color:#2E86AB'>Qt富文本演示</h2>")
+ "<p>支持 <b>加粗</b>、<<i>斜体</</i>、<u>下划线</u></p>"
+ "<p>支持图片:<img src=':/images/qt-logo.png' width='100' height='100'></p>"
+ "<table border='1'>"
+ "<tr><<th>姓名</</th><<th>年龄</</th></tr>"
+ "<tr><td>张三</td><td>20</td></tr>"
+ "</table>";
htmlEdit->setHtml(htmlText);
// Markdown标签页
QTextEdit *markdownEdit = new QTextEdit(this);
markdownEdit->setReadOnly(true);
QString markdownText = QString("## Markdown演示\n")
+ "- 支持无序列表\n"
+ "- 支持**加粗**、*斜体*\n"
+ "`代码片段`\n"
+ "> 引用文本块\n"
+ "### 三级标题\n"
+ "1. 有序列表1\n"
+ "2. 有序列表2";
markdownEdit->setMarkdown(markdownText);
tabWidget->addTab(htmlEdit, "HTML格式");
tabWidget->addTab(markdownEdit, "Markdown格式");
layout->addWidget(tabWidget);
}
3.3 TextEdit 避坑指南
问题 1:Markdown 格式不生效?
- 原因:Qt 5.14 及以上才支持 Markdown,低版本需手动解析;
- 解决方案:升级 Qt 版本,或使用第三方 Markdown 解析库(如 MarkdownQt)。
问题 2:TextEdit 自动换行后,光标位置计算错误?
- 原因:自动换行后,**position()**返回的是字符位置,而非视觉行数;
- 解决方案:通过**textCursor().blockNumber()**获取当前行数(从 0 开始)。
问题 3:插入图片后,程序打包后图片丢失?
- 原因:图片路径为绝对路径,打包后路径失效;
- 解决方案:使用 Qt 资源文件(.qrc)管理图片,通过
:/前缀/文件名引用。
四、ComboBox:下拉选择的 "高效控件"
QComboBox 是下拉选项控件,支持固定选项选择、可编辑输入,适用于分类筛选、菜单选择等场景,能节省界面空间,提升操作效率。

4.1 核心属性与 API
ComboBox 的核心属性围绕 "选项管理" 和 "编辑行为" 展开:
| 属性名 | 功能说明 | 实用场景 |
|---|---|---|
| currentText | 当前选中的文本 | 获取用户选择结果 |
| currentIndex | 当前选中的选项下标(从 0 开始,未选中为 - 1) | 批量选项管理 |
| editable | 是否允许编辑(可输入自定义内容) | 支持 "选择 + 输入" 混合场景 |
| iconSize | 选项图标的尺寸 | 带图标的下拉菜单 |
| maxCount | 最大选项数量 | 限制选项个数 |
| placeholderText | 可编辑模式下的提示文本 | 引导用户输入 / 选择 |
核心 API:
- addItem(const QString& text):添加单个选项
- addItems(const QStringList& items):批量添加选项
- insertItem(int index, const QString& text):在指定位置插入选项
- removeItem(int index):删除指定下标选项
- clear():清空所有选项
- currentIndexChanged(int index):选中选项变化时触发的信号
4.2 基础用法:固定选项与可编辑模式
4.2.1 固定选项下拉框(分类选择)
先编辑.ui文件:

编写代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->comboBox->addItem("麦辣鸡腿堡");
ui->comboBox->addItem("巨无霸");
ui->comboBox->addItem("培根蔬萃双层牛堡");
ui->comboBox_2->addItem("中薯条");
ui->comboBox_2->addItem("麦乐鸡块");
ui->comboBox_2->addItem("麦辣鸡翅");
ui->comboBox_3->addItem("可乐");
ui->comboBox_3->addItem("雪碧");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
qDebug() << ui->comboBox->currentText() << ", " << ui->comboBox_2->currentText() << ", " << ui->comboBox_3->currentText();
}
运行结果如下:

4.2.2 可编辑下拉框(支持输入 + 选择)
cpp
#include "widget.h"
#include <QComboBox>
#include <QLabel>
#include <QVBoxLayout>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("ComboBox可编辑模式");
QVBoxLayout *layout = new QVBoxLayout(this);
QLabel *cityLabel = new QLabel("请选择/输入城市:", this);
QComboBox *cityBox = new QComboBox(this);
// 设置为可编辑模式
cityBox->setEditable(true);
cityBox->setPlaceholderText("请选择或输入城市");
// 添加常用城市选项
QStringList cities = {"北京", "上海", "广州", "深圳", "杭州", "成都"};
cityBox->addItems(cities);
layout->addWidget(cityLabel);
layout->addWidget(cityBox);
// 编辑文本变化时触发
connect(cityBox, &QComboBox::editTextChanged, this, [=](const QString& text) {
qDebug() << "输入/选择的城市:" << text;
});
}
4.3 实战案例:从文件加载下拉选项
实际开发中,下拉选项常存储在配置文件中(如 txt、ini),通过读取文件动态加载选项:
我们先准备一个.txt文件,用于载入到下拉选项中:


依旧编辑.ui文件:

编辑代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <fstream>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//读取文件内容,把文件中的每一行读取出来,作为一个ComboBox的选项
std::ifstream file("C:/Users/ASUS/Desktop/config.txt");
if(!file.is_open())
{
qDebug() << "文件打开失败";
return;
}
//按行来读取文本内容
//通过getline函数完成
std::string line;
while(std::getline(file, line))
{
//取到的每一行内容,设置到下拉框中
ui->comboBox->addItem(QString::fromStdString(line));
}
file.close();
}
Widget::~Widget()
{
delete ui;
}
运行结果:

4.4 ComboBox 避坑指南
问题 1:添加选项后,currentIndex始终为 - 1?
- 原因:未设置默认选中项,且用户未手动选择;
- 解决方案:通过**setCurrentIndex(0)**设置默认选中第一个选项。
问题 2:可编辑模式下,输入的文本不会添加到选项列表?
- 原因:默认情况下,编辑文本仅临时有效,不会自动添加到选项;
- 解决方案:在editTextChanged信号中,手动调用addItem添加新选项。
问题 3:从文件加载选项时,中文乱码?
- 原因:文件编码与 Qt 默认编码不一致(Qt 默认 UTF-8);
- 解决方案:将文件保存为 UTF-8 编码,或在读取时指定编码。
五、SpinBox/DoubleSpinBox:数值微调的 "精准工具"
QSpinBox(整数微调框) 和 **QDoubleSpinBox(浮点数微调框)**是专门用于数值输入的控件,支持步长调整、范围限制、前缀后缀,适用于数量选择、参数调节等场景。
5.1 核心属性与 API
两者属性和 API 基本一致,仅数值类型不同(int/double):
| 属性名 | 功能说明 | 实用场景 |
|---|---|---|
| value | 当前数值 | 获取 / 设置数值 |
| minimum | 最小值 | 限制数值下限(如数量≥1) |
| maximum | 最大值 | 限制数值上限(如数量≤10) |
| singleStep | 步长(每次点击按钮变化的数值) | 精准调节(如步长 0.1) |
| prefix | 前缀文本(如 "¥""数量:") | 数值单位提示 |
| suffix | 后缀文本(如 "元""kg") | 数值单位提示 |
| wrapping | 是否循环(超过最大值后回到最小值) | 循环调节场景 |
| readOnly | 只读模式(仅展示,不可编辑) | 展示固定数值 |
| correctionMode | 输入错误时的修正方式(回退到上一个有效值 / 最近有效值) | 避免非法数值 |
核心 API:
- value():获取当前数值
- setValue(double/int value):设置数值
- setRange(double/int min, double/int max):设置数值范围
- valueChanged(double/int value):数值变化时触发的信号
5.2 基础用法:微调数字
先编辑.ui文件:

编辑代码如下:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//初始化下拉菜单
ui->comboBox->addItem("麦辣鸡腿堡");
ui->comboBox->addItem("巨无霸");
ui->comboBox->addItem("培根薯脆双层牛堡");
ui->comboBox_2->addItem("中薯条");
ui->comboBox_2->addItem("麦乐鸡块");
ui->comboBox_2->addItem("麦辣鸡翅");
ui->comboBox_3->addItem("雪碧");
ui->comboBox_3->addItem("可乐");
//针对QSpinBox的范围进行设置
ui->spinBox->setRange(1, 5);
ui->spinBox_2->setRange(1, 5);
ui->spinBox_3->setRange(1, 5);
ui->spinBox->setValue(1);
ui->spinBox_2->setValue(1);
ui->spinBox_3->setValue(1);
}
Widget::~Widget()
{
delete ui;
}
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.3 SpinBox 避坑指南
问题 1:DoubleSpinBox 显示多位小数,精度丢失?
- 原因:double类型本身存在精度误差,且decimals属性设置过高;
- 解决方案:通过setDecimals(int n)限制小数位数(如 2 位),或使用QDecimal类处理高精度数值。
问题 2:设置wrapping=true后,数值超过最大值不循环?
- 原因:wrapping仅在通过按钮调整时生效,手动输入超过范围的数值不会循环;
- 解决方案:结合valueChanged信号,手动处理数值循环逻辑。
问题 3:输入非法数值(如字母)后,数值不变?
- 原因:correctionMode默认设为CorrectToPreviousValue,输入非法值会回退到上一个有效值;
- 解决方案:根据需求修改correctionMode,或在valueChanged中添加非法值提示。
六、DateEdit/TimeEdit/DateTimeEdit:日期时间的 "标准输入"
QDateEdit(日期输入)、QTimeEdit(时间输入)、QDateTimeEdit(日期时间输入)是 Qt 提供的标准化日期时间输入控件,支持格式自定义、范围限制,避免非法日期时间输入。

6.1 核心属性与 API
三者核心属性一致,仅处理的时间维度不同:
| 属性名 | 功能说明 | 实用场景 |
|---|---|---|
| date/time/dateTime | 当前选中的日期 / 时间 / 日期时间 | 获取用户输入的日期时间 |
| minimumDate/minimumTime/minimumDateTime | 最小日期 / 时间 / 日期时间 | 限制不能选择过去的日期(如预约场景) |
| maximumDate/maximumTime/maximumDateTime | 最大日期 / 时间 / 日期时间 | 限制不能选择过远的日期(如 30 天内) |
| displayFormat | 显示格式(如 "yyyy-MM-dd""HH:mm:ss") | 自定义日期时间显示样式 |
| timeSpec | 时间标准(LocalTime/UTC/OffsetFromUTC) | 本地时间或 UTC 时间切换 |
| calendarPopup | 是否显示日历弹窗(仅 DateEdit/DateTimeEdit) | 点击输入框弹出日历选择 |
核心 API:
- date()/time()/dateTime():获取日期 / 时间 / 日期时间
- setDate(const QDate& date):设置日期
- setDisplayFormat(const QString& format):设置显示格式
- dateChanged(const QDate& date):日期变化时触发的信号
6.2 日期计算器(计算两个日期的天数差)
先编辑.ui文件:

编写代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
//1.先获取到两个输入框之间的时间都是啥
QDateTime timeOld = ui->dateTimeEdit->dateTime();
QDateTime timeNew = ui->dateTimeEdit_2->dateTime();
qDebug() << timeOld << timeNew;
//2.计算日期的差值
//int days = timeOld.daysTo(timeNew);
int seconds = timeOld.secsTo(timeNew);
//3.要把秒数换算成小时
int hours = (seconds / 3600) % 24;
int days = (seconds / 3600) / 24;
//4.把计算结果放到label中
ui->label->setText(QString("爱你已经持续了 ") + QString::number(days)
+ QString(" 天零 ") + QString::number(hours) + QString(" 小时"));
}
运行结果:

关键技术点:
- daysTo(const QDate& date):计算两个日期之间的天数差;
- secsTo(const QDateTime& dateTime):计算两个日期时间之间的秒数差;
- 时间换算:1 小时 = 3600 秒,1 分钟 = 60 秒,通过取模和除法换算成小时、分钟。
6.3 日期时间控件避坑指南
问题 1:显示格式不生效(如 "yyyy-MM-dd" 显示为 "2025/01/01")?
- 原因:格式符错误(如大小写错误,"MM" 表示月份,"mm" 表示分钟);
- 解决方案:正确使用格式符:
- 日期:yyyy(年)、MM(月)、dd(日)、ddd(星期缩写);
- 时间:HH(24 小时制)、hh(12 小时制)、mm(分钟)、ss(秒)。
问题 2:日历弹窗不显示?
- 原因:
calendarPopup属性未设为 true,或控件为 QTimeEdit(不支持日历弹窗);- 解决方案:对 QDateEdit/DateTimeEdit 设置
setCalendarPopup(true)。
问题 3:设置minimumDate后,仍能手动输入过去的日期?
- 原因:手动输入未触发范围校验;
- 解决方案:结合
dateChanged信号,手动校验日期是否在范围内,超出则重置为最小值。
七、Dial:通过旋钮调节的直观控件
QDial 是旋钮式调节控件,通过旋转旋钮实现数值调节,适用于音量、亮度、透明度等需要直观调节的场景,操作体验更符合物理直觉。

7.1 核心属性与 API
Dial 的核心属性围绕 "数值调节" 和 "外观样式" 展开:
| 属性名 | 功能说明 | 实用场景 |
|---|---|---|
| value | 当前数值 | 获取 / 设置调节值 |
| minimum | 最小值 | 调节范围下限 |
| maximum | 最大值 | 调节范围上限 |
| singleStep | 按下方向键时的步长 | 精准调节 |
| pageStep | 按下 PageUp/PageDown 时的步长 | 快速调节 |
| wrapping | 是否循环调节(超过最大值后回到最小值) | 循环调节场景(如音量) |
| notchesVisible | 是否显示刻度线 | 直观展示调节范围 |
| notchTarget | 刻度线之间的数值间隔(值越大,刻度越稀疏) | 控制刻度密度 |
| tracking | 外观是否跟踪数值变化(默认 true) | 实时反馈调节结果 |
核心 API:
- value():获取当前数值
- setValue(int value):设置数值
- setRange(int min, int max):设置调节范围
- valueChanged(int value):数值变化时触发的信号
7.2 基础用法:旋钮调节
编辑.ui文件:

运行文件,发现可以自由旋转旋钮控件:

7.3 实战案例:旋钮调节窗口透明度
结合 Dial 和窗口透明度属性,实现直观的透明度调节:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_dial_valueChanged(int value)
{
qDebug() << value;
this->setWindowOpacity((double)(value / 100));
}
运行结果如下:

可以发现窗口透明度随着旋钮的条件而改变。
7.4 Dial 避坑指南
问题 1:旋钮旋转时,数值变化不流畅?
- 原因:singleStep步长过大,或notchTarget过小导致刻度过密;
- 解决方案:减小singleStep(如设为 1),增大notchTarget(如设为 5)。
问题 2:wrapping=true后,旋转到最大值不循环?
- 原因:旋钮旋转角度未达到 "循环阈值",或数值范围设置不合理;
- 解决方案:确保minimum和maximum差值足够大(如≥10),或调整旋钮旋转灵敏度。
问题 3:刻度线不显示?
- 原因:notchesVisible未设为 true,或notchTarget为 0;
- 解决方案:设置setNotchesVisible(true),并指定notchTarget(如 10)。
八、Slider:滑动条调节的经典控件
QSlider 是滑动条式调节控件,支持水平 / 垂直方向,通过拖动滑块实现数值调节,适用于进度控制、参数调节等场景,是最常用的调节类控件之一。

8.1 核心属性与 API
Slider 与 Dial 属性高度相似,核心差异在于外观和操作方式:
| 属性名 | 功能说明 | 实用场景 |
|---|---|---|
| value | 当前数值 | 获取 / 设置调节值 |
| minimum | 最小值 | 调节范围下限 |
| maximum | 最大值 | 调节范围上限 |
| singleStep | 按下方向键时的步长 | 精准调节 |
| pageStep | 按下 PageUp/PageDown 时的步长 | 快速调节 |
| orientation | 方向(Horizontal/Vertical) | 水平(进度条)/ 垂直(侧边调节) |
| invertedAppearance | 是否翻转调节方向(如滑块从右向左增长) | 反向调节场景 |
| tickPosition | 刻度线位置(NoTicks/TicksAbove/TicksBelow/TicksBothSides) | 刻度显示位置 |
| tickInterval | 刻度线之间的数值间隔 | 控制刻度密度 |
核心 API:
- 与 Dial 一致,新增**setOrientation(Qt::Orientation orientation)**设置方向。
8.2 通过滑动条调节窗口大小
先在.ui文件中拖入两个滑动条控件:

编写代码如下:
cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->horizontalSlider->setMinimum(100);
ui->horizontalSlider->setMaximum(2000);
ui->horizontalSlider->setValue(800);
ui->horizontalSlider->setSingleStep(500);
ui->verticalSlider->setMinimum(100);
ui->verticalSlider->setMaximum(1500);
ui->verticalSlider->setValue(600);
ui->verticalSlider->setSingleStep(50);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_horizontalSlider_valueChanged(int value)
{
const QRect& rect = this->geometry();
this->setGeometry(rect.x(), rect.y(), value, rect.height());
}
void Widget::on_verticalSlider_valueChanged(int value)
{
const QRect& rect = this->geometry();
this->setGeometry(rect.x(), rect.y(), rect.width(), value);
}
运行结果:


我们就实现了通过拖动滑动条来控制窗口大小和比例。
8.3 快捷键控制滑动条
通过自定义快捷键(如 "-" 减小数值、"=" 增大数值),实现滑动条的键盘控制:
依旧先编辑.ui文件:

编写代码:
cpp
#include "widget.h"
#include "ui_widget.h"
#include <QShortcut>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//使用快捷键,需要用到QShortCut类
//需要两个快捷键,- 进行减少,=进行增加(+和=是同一个按钮)
QShortcut* shortCut1 = new QShortcut(this);
shortCut1->setKey(QKeySequence("-"));
QShortcut* shortCut2 = new QShortcut(this);
shortCut2->setKey(QKeySequence("="));
//使用信号槽,感知到快捷键被按下
connect(shortCut1, &QShortcut::activated, this, &Widget::subValue);
connect(shortCut2, &QShortcut::activated, this, &Widget::addValue);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_horizontalSlider_valueChanged(int value)
{
ui->label->setText("当前的值为:" + QString::number(value));
}
void Widget::subValue()
{
//获取到当前的值
int value = ui->horizontalSlider->value();
if(value <= ui->horizontalSlider->minimum())
{
return;
}
ui->horizontalSlider->setValue(value - 5);
}
void Widget::addValue()
{
//获取到当前的值
int value = ui->horizontalSlider->value();
if(value >= ui->horizontalSlider->maximum())
{
return;
}
ui->horizontalSlider->setValue(value + 5);
}
运行结果如下:

先在我们就可以通过快捷键"="("+")使滑动条右移,"-"使滑动条左移了。
8.5 Slider 避坑指南
问题 1:滑动条拖动时,数值变化滞后?
- 原因:tracking属性设为 false(默认 true),仅释放滑块时触发valueChanged;
- 解决方案:设置setTracking(true),实时触发数值变化。
问题 2:垂直滑动条调节方向与预期相反?
- 原因:invertedAppearance设为 true,滑块从下向上增长;
- 解决方案:设置setInvertedAppearance(false),或根据需求调整方向。
问题 3:刻度线不显示?
- 原因:tickPosition设为NoTicks,或tickInterval为 0;
- 解决方案:设置tickPosition为TicksAbove/TicksBelow,并指定tickInterval(如 10)。
总结
本文详细讲解了 Qt 中 7 种核心输入类控件的使用方法,从基础属性到实战案例,覆盖了单行输入、多行编辑、下拉选择、数值调节、日期时间输入等所有输入场景。掌握好这7种输入类控件的使用,能够对日后的客户端开发打下坚实的基础。如果大家有疑问的话欢迎在评论区留言讨论~
