【从零开始的Qt开发指南】(十)Qt 常用控件之输入类控件全攻略:7 大控件从入门到实战,覆盖所有输入场景


目录

前言

一、输入类控件的核心价值

[二、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后,仍能手动输入过去的日期?)

七、Dial:通过旋钮调节的直观控件

[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:刻度线不显示?)

八、Slider:滑动条调节的经典控件

[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:inputMaskvalidator同时使用时冲突?

  • 原因:两者都用于输入约束,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后,旋转到最大值不循环?

  • 原因:旋钮旋转角度未达到 "循环阈值",或数值范围设置不合理;
  • 解决方案:确保minimummaximum差值足够大(如≥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;
  • 解决方案:设置tickPositionTicksAbove/TicksBelow,并指定tickInterval(如 10)。

总结

本文详细讲解了 Qt 中 7 种核心输入类控件的使用方法,从基础属性到实战案例,覆盖了单行输入、多行编辑、下拉选择、数值调节、日期时间输入等所有输入场景。掌握好这7种输入类控件的使用,能够对日后的客户端开发打下坚实的基础。如果大家有疑问的话欢迎在评论区留言讨论~

相关推荐
阿里嘎多学长5 小时前
2025-12-15 GitHub 热点项目精选
开发语言·程序员·github·代码托管
一只乔哇噻5 小时前
java后端工程师+AI大模型开发进修ing(研一版‖day63)
java·开发语言·人工智能·python·语言模型
小白学大数据5 小时前
从爬取到分析:使用 Pandas 处理头条问答数据
开发语言·爬虫·python·pandas
爱吃大芒果5 小时前
Flutter 状态管理全家桶:Provider、Bloc、GetX 实战对比
开发语言·前端·javascript·flutter·华为·ecmascript
想不明白的过度思考者5 小时前
Java网络聊天室——OverThinker-ChatRoom
java·开发语言·网络
过期动态5 小时前
JDBC进阶篇:拓展功能与连接池运用详解
java·开发语言·数据库·mysql·oracle·intellij-idea·mybatis
布伦鸽5 小时前
C# WPF -MaterialDesignTheme 找不到资源“xxx“问题记录
开发语言·c#·wpf
枫叶丹45 小时前
【Qt开发】Qt窗口(十) -> QInputDialog 输入对话框
c语言·开发语言·数据库·c++·qt
云青山水林5 小时前
算法竞赛从入门到跳楼(ACM-XCPC、蓝桥杯软件赛等)
c++·算法·蓝桥杯