第十三章:QT对话框——让程序与用户优雅对话
对话框这东西,说白了就是程序跟用户「搭话」的窗口。你想想看,用户要打开文件、选个颜色、改个字体,总不能让人家去敲代码吧?这时候对话框就派上用场了。QT 给我们准备了一整套现成的对话框,用起来相当顺手。
我个人习惯把对话框分成两类:一类是系统自带的「标准对话框」,开箱即用;另一类是「自定义对话框」,满足特殊需求。今天咱们就把这两类都过一遍。
13.1 QMessageBox——消息提示的好帮手
QMessageBox 是我用得最频繁的对话框。不管是提示用户「保存成功」,还是警告「操作不可逆」,它都能搞定。
先看一个最简单的用法:
QMessageBox::information(this, "提示", "文件已保存");
这一行代码就能弹出一个信息提示框。QT 提供了几种常用类型:
| 静态方法 | 图标 | 适用场景 |
|---|---|---|
| QMessageBox::information() | i 图标 | 普通信息提示 |
| QMessageBox::warning() | ⚠ 图标 | 警告用户注意 |
| QMessageBox::critical() | ✖ 图标 | 严重错误提示 |
| QMessageBox::question() | ❓ 图标 | 询问用户选择 |
| QMessageBox::about() | 程序图标 | 关于对话框 |
我曾经在做一个数据导出功能时,用户点了导出按钮后程序直接卡死——因为没有加「正在处理」的提示。后来我加了个 QMessageBox,用户体验立马好了很多。
如果你需要用户做选择,用 question 最合适:
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确认", "确定要删除这条记录吗?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) {
// 执行删除操作
}
13.2 QFileDialog——文件选择不求人
文件对话框,每个桌面应用几乎都离不开。QT 的 QFileDialog 封装得很完善,打开文件、保存文件、选择目录,一行代码搞定。
打开单个文件:
QString fileName = QFileDialog::getOpenFileName(this, "选择图片",
"/home/user",
"图片文件 (*.png *.jpg *.bmp)");
if (!fileName.isEmpty()) {
// 加载图片
}
打开多个文件:
QStringList files = QFileDialog::getOpenFileNames(this, "选择多个文件",
"/home/user",
"所有文件 (*)");
foreach (QString file, files) {
qDebug() << "选中了:" << file;
}
保存文件:
QString savePath = QFileDialog::getSaveFileName(this, "保存报告",
"report.txt",
"文本文件 (*.txt);;PDF文件 (*.pdf)");
if (!savePath.isEmpty()) {
// 写入文件
}
选择目录:
QString dir = QFileDialog::getExistingDirectory(this, "选择工作目录",
"/home/user");
if (!dir.isEmpty()) {
// 设置工作目录
}
13.3 QColorDialog——颜色选择器
如果你的应用需要让用户自定义颜色,QColorDialog 就是你的救星。它提供了一个完整的颜色选择界面,支持 RGB、HSV 等多种颜色模式。
QColor color = QColorDialog::getColor(Qt::white, this, "选择背景色");
if (color.isValid()) {
// 使用选中的颜色
ui->widget->setStyleSheet(QString("background-color: %1").arg(color.name()));
}
这里有个细节:getColor 的第一个参数是默认颜色,第二个是父窗口,第三个是对话框标题。返回的 QColor 对象用 isValid() 判断用户是否真的选了一个颜色。
我记得有一次做绘图工具,用户反馈说「选颜色时能不能记住上次选的颜色?」。解决方案很简单:用一个成员变量保存上次选中的颜色,每次打开对话框时传进去作为默认值。
13.4 QFontDialog——字体设置不求人
字体对话框和颜色对话框很像,都是让用户从预设选项里挑一个。不过字体对话框返回的是 QFont 对象,包含了字体名称、大小、粗体、斜体等信息。
bool ok;
QFont font = QFontDialog::getFont(&ok, QFont("微软雅黑", 12), this, "选择字体");
if (ok) {
// 应用字体
ui->textEdit->setFont(font);
}
注意那个 &ok 参数。它是一个输出参数,用户点了「确定」就设为 true,点了「取消」就是 false。这样你就能区分用户是「选好了」还是「不想选了」。
13.5 QInputDialog——简单输入场景
有时候你只需要用户输入一个数字、一段文字或者从列表里选一项。这时候用 QInputDialog 最合适,它不会像 QDialog 那样「大动干戈」。
获取文本输入:
bool ok;
QString text = QInputDialog::getText(this, "输入姓名", "请输入您的姓名:",
QLineEdit::Normal, "", &ok);
if (ok && !text.isEmpty()) {
// 处理输入
}
获取整数输入:
int value = QInputDialog::getInt(this, "设置数量", "请输入数量:",
10, 0, 100, 1, &ok);
if (ok) {
// 使用数值
}
从列表中选择:
QStringList items;
items << "选项A" << "选项B" << "选项C";
QString item = QInputDialog::getItem(this, "选择模式", "请选择一种模式:",
items, 0, false, &ok);
if (ok) {
// 处理选择
}
getInt 的参数依次是:父窗口、标题、标签、默认值、最小值、最大值、步长、是否成功。这个函数我特别喜欢,因为它自带输入验证——用户想输入「abc」都输不进去。
13.6 自定义对话框——当标准对话框不够用
标准对话框虽然方便,但总有满足不了需求的时候。比如你要做一个「用户登录」对话框,总不能指望 QInputDialog 能搞定吧?这时候就需要自己动手了。
自定义对话框的核心思路:继承 QDialog,在构造函数里布局控件,然后通过信号或成员函数获取用户输入。
// LoginDialog.h
class LoginDialog : public QDialog {
Q_OBJECT
public:
explicit LoginDialog(QWidget *parent = nullptr);
QString username() const;
QString password() const;
private:
QLineEdit *m_usernameEdit;
QLineEdit *m_passwordEdit;
QPushButton *m_okBtn;
QPushButton *m_cancelBtn;
};
// LoginDialog.cpp
LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent) {
setWindowTitle("用户登录");
setFixedSize(300, 200);
m_usernameEdit = new QLineEdit(this);
m_passwordEdit = new QLineEdit(this);
m_passwordEdit->setEchoMode(QLineEdit::Password);
m_okBtn = new QPushButton("登录", this);
m_cancelBtn = new QPushButton("取消", this);
// 布局
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addWidget(new QLabel("用户名:"));
mainLayout->addWidget(m_usernameEdit);
mainLayout->addWidget(new QLabel("密码:"));
mainLayout->addWidget(m_passwordEdit);
QHBoxLayout *btnLayout = new QHBoxLayout();
btnLayout->addStretch();
btnLayout->addWidget(m_okBtn);
btnLayout->addWidget(m_cancelBtn);
mainLayout->addLayout(btnLayout);
connect(m_okBtn, &QPushButton::clicked, this, &QDialog::accept);
connect(m_cancelBtn, &QPushButton::clicked, this, &QDialog::reject);
}
QString LoginDialog::username() const {
return m_usernameEdit->text();
}
QString LoginDialog::password() const {
return m_passwordEdit->text();
}
使用的时候:
LoginDialog dlg(this);
if (dlg.exec() == QDialog::Accepted) {
QString user = dlg.username();
QString pwd = dlg.password();
// 验证登录
}
13.7 知识体系总览
下面这张图把本章的对话框体系梳理了一下,方便你对照着看:
嗯,这张图把今天讲的内容串起来了。你可以看到,标准对话框覆盖了大部分常见场景,自定义对话框则用来处理那些「特殊需求」。两者结合,基本能应对所有用户交互场景。
最后说一句:对话框的设计要「轻量」。用户打开对话框是为了快速完成一个操作,不是来参观你的 UI 设计的。保持简洁,保持清晰,这就是好对话框的标准。
公众号:蓝海资料掘金营,微信deep3321