【Qt/C++ 桌面开发实战营】第6篇:Qt对话框系统
·
系列介绍
这是系列文章的第六篇,我将带你全面学习Qt的对话框系统。对话框是与用户交互的重要方式,掌握它们能让你的程序更加友好和专业。
🎯 本篇你将学到:
-
标准消息对话框的使用
-
文件对话框和输入对话框
-
颜色和字体对话框
-
进度对话框
-
自定义对话框的创建
-
向导对话框的实现
🏆 系列进度:
-
✅ 第1篇:Qt环境搭建与第一个Hello World
-
✅ 第2篇:Qt信号槽机制详解
-
✅ 第3篇:Qt布局管理器完全指南
-
✅ 第4篇:Qt样式表QSS美化教程
-
✅ 第5篇:Qt常用控件全解析
-
📝 第6篇:Qt对话框系统(本篇)
-
🔜 第7篇:QProcess调用外部程序
让我们开始吧!
一、对话框概述
1.1 什么是对话框?
对话框是用于与用户进行短期交互的窗口,通常用于:
-
显示信息或警告
-
获取用户输入
-
确认操作
-
进度展示
-
设置选项
┌─────────────────────────────────────────────────────────────┐
│ 主窗口 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 内容区域 │ │
│ │ │ │
│ │ [打开文件] ← 点击按钮 │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼ 弹出对话框
┌─────────────────────────────────────────────────────────────┐
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 选择文件 [×] │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ 📁 桌面 │ │ │
│ │ │ 📄 文档1.pdf │ │ │
│ │ │ 📄 文档2.pdf │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ │ [取消] [打开] │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
1.2 对话框的分类
| 类型 | 说明 | 常用类 |
|---|---|---|
| 模态对话框 | 阻止与其它窗口交互 | 大部分对话框 |
| 非模态对话框 | 可同时操作其他窗口 | QDialog::setModal(false) |
| 标准对话框 | Qt内置的常用对话框 | QMessageBox, QFileDialog |
| 自定义对话框 | 用户自己设计的对话框 | QDialog子类 |
1.3 模态 vs 非模态
// 模态对话框(阻塞) QDialog dialog(this); dialog.exec(); // 代码会阻塞在这里,直到对话框关闭 // 非模态对话框(不阻塞) QDialog *dialog = new QDialog(this); dialog->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动删除 dialog->show(); // 不阻塞,立即返回
模态效果:
┌─────────────────┐ ┌─────────────────┐ │ 主窗口 │ │ 主窗口 │ │ │ │ (不可点击) │ │ [按钮] 灰色 │ → │ │ │ │ │ ┌─────────┐ │ │ │ │ │ 对话框 │ │ │ │ │ └─────────┘ │ └─────────────────┘ └─────────────────┘
二、标准消息对话框
2.1 QMessageBox基础用法
QMessageBox是最常用的对话框,用于显示信息、警告、错误或询问确认。
// 最简单的用法
QMessageBox::information(this, "标题", "这是一条信息");
// 带按钮的确认对话框
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确认", "是否保存更改?",
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (reply == QMessageBox::Yes) {
// 保存逻辑
} else if (reply == QMessageBox::No) {
// 不保存逻辑
} else {
// 取消操作
}
2.2 四种标准对话框
// 1. 信息对话框
QMessageBox::information(this, "提示", "操作已完成!");
// 2. 警告对话框
QMessageBox::warning(this, "警告", "文件不存在,请检查路径!");
// 3. 错误对话框
QMessageBox::critical(this, "错误", "程序遇到未知错误,即将退出。");
// 4. 提问对话框
QMessageBox::StandardButton result;
result = QMessageBox::question(this, "确认删除",
"确定要删除选中的文件吗?\n此操作不可撤销!",
QMessageBox::Yes | QMessageBox::No);
视觉效果:
┌─────────────────────────────────────┐ │ 提示 [×] │ ├─────────────────────────────────────┤ │ ℹ️ │ │ 操作已完成! │ │ │ │ [确定] │ └─────────────────────────────────────┘ ┌─────────────────────────────────────┐ │ 确认删除 [×] │ ├─────────────────────────────────────┤ │ ❓ │ │ 确定要删除选中的文件吗? │ │ 此操作不可撤销! │ │ │ │ [是] [否] [取消] │ └─────────────────────────────────────┘
2.3 高级定制
// 创建自定义消息框
QMessageBox msgBox(this);
msgBox.setWindowTitle("关于");
msgBox.setIcon(QMessageBox::Information);
msgBox.setText("<b>PDF全能工具箱</b>");
msgBox.setInformativeText("版本: 1.0.0\n作者: Your Name\n\n一个免费的PDF处理工具。");
// 添加自定义按钮
QPushButton *githubBtn = msgBox.addButton("访问GitHub", QMessageBox::ActionRole);
QPushButton *closeBtn = msgBox.addButton(QMessageBox::Close);
msgBox.exec();
if (msgBox.clickedButton() == githubBtn) {
QDesktopServices::openUrl(QUrl("https://github.com/..."));
}
// 设置详细文本(错误详情)
QMessageBox errorBox;
errorBox.setIcon(QMessageBox::Critical);
errorBox.setWindowTitle("错误");
errorBox.setText("无法打开文件");
errorBox.setDetailedText("错误详情:\n文件路径:C:/test.pdf\n错误代码:0x80070002\n文件不存在。");
errorBox.exec();
带详细信息的错误框:
┌─────────────────────────────────────────────────┐ │ 错误 [×] │ ├─────────────────────────────────────────────────┤ │ ❌ │ │ 无法打开文件 │ │ │ │ 详细信息 ▼ │ │ ┌───────────────────────────────────────────┐ │ │ │ 错误详情: │ │ │ │ 文件路径:C:/test.pdf │ │ │ │ 错误代码:0x80070002 │ │ │ │ 文件不存在。 │ │ │ └───────────────────────────────────────────┘ │ │ [确定] │ └─────────────────────────────────────────────────┘
2.4 可用的标准按钮
QMessageBox::StandardButton 类型: - QMessageBox::Ok // 确定 - QMessageBox::Cancel // 取消 - QMessageBox::Yes // 是 - QMessageBox::No // 否 - QMessageBox::Save // 保存 - QMessageBox::Discard // 丢弃 - QMessageBox::Apply // 应用 - QMessageBox::Reset // 重置 - QMessageBox::Close // 关闭 - QMessageBox::Abort // 中止 - QMessageBox::Retry // 重试 - QMessageBox::Ignore // 忽略
2.5 辅助函数封装
// 在实际项目中,可以封装成方便使用的函数
class MessageBoxHelper {
public:
static void showInfo(QWidget *parent, const QString &title, const QString &msg) {
QMessageBox::information(parent, title, msg);
}
static void showError(QWidget *parent, const QString &title, const QString &msg) {
QMessageBox::critical(parent, title, msg);
}
static bool confirm(QWidget *parent, const QString &title, const QString &msg) {
return QMessageBox::question(parent, title, msg,
QMessageBox::Yes | QMessageBox::No)
== QMessageBox::Yes;
}
static bool confirmDelete(QWidget *parent, const QString &itemName) {
return QMessageBox::question(parent, "确认删除",
QString("确定要删除「%1」吗?\n此操作不可撤销!").arg(itemName),
QMessageBox::Yes | QMessageBox::No)
== QMessageBox::Yes;
}
};
// 使用示例
MessageBoxHelper::showInfo(this, "提示", "操作成功!");
if (MessageBoxHelper::confirm(this, "确认", "是否保存更改?")) {
// 保存逻辑
}
if (MessageBoxHelper::confirmDelete(this, filePath)) {
QFile::remove(filePath);
}
三、文件对话框
3.1 QFileDialog基础用法
#include <QFileDialog>
// 打开单个文件
QString filePath = QFileDialog::getOpenFileName(this,
"选择文件",
QDir::homePath(),
"PDF文件 (*.pdf);;所有文件 (*.*)");
if (!filePath.isEmpty()) {
qDebug() << "选择的文件:" << filePath;
}
// 打开多个文件
QStringList files = QFileDialog::getOpenFileNames(this,
"选择多个文件",
QDir::homePath(),
"PDF文件 (*.pdf)");
foreach (QString file, files) {
qDebug() << file;
}
// 保存文件对话框
QString savePath = QFileDialog::getSaveFileName(this,
"保存文件",
QDir::homePath() + "/未命名.pdf",
"PDF文件 (*.pdf)");
// 选择目录
QString dirPath = QFileDialog::getExistingDirectory(this,
"选择目录",
QDir::homePath());
3.2 文件过滤器详解
// 单个过滤器
QString filter = "图片文件 (*.png *.jpg *.bmp)";
// 多个过滤器(用;;分隔)
QString filter = "PDF文件 (*.pdf);;Word文件 (*.doc *.docx);;Excel文件 (*.xls *.xlsx);;所有文件 (*.*)";
// 使用示例
QString filePath = QFileDialog::getOpenFileName(this, "打开文件",
QDir::homePath(),
filter,
&selectedFilter); // 返回用户选择的过滤器
3.3 高级选项
QFileDialog dialog(this);
dialog.setWindowTitle("选择文件");
dialog.setFileMode(QFileDialog::ExistingFiles); // 多选模式
dialog.setNameFilter("PDF文件 (*.pdf)");
dialog.setViewMode(QFileDialog::Detail); // 详细视图(列表+详情)
dialog.setOption(QFileDialog::DontUseNativeDialog, false); // 使用系统原生对话框
// 设置默认后缀
dialog.setDefaultSuffix("pdf");
if (dialog.exec()) {
QStringList files = dialog.selectedFiles();
// 处理文件...
}
// 可用的文件模式
// QFileDialog::AnyFile 任意文件(保存时)
// QFileDialog::ExistingFile 已存在的文件(打开时)
// QFileDialog::ExistingFiles 多个文件
// QFileDialog::Directory 目录
// QFileDialog::DirectoryOnly 仅目录
四、输入对话框
4.1 QInputDialog基础用法
#include <QInputDialog>
// 文本输入
bool ok;
QString text = QInputDialog::getText(this, "输入姓名",
"请输入您的姓名:",
QLineEdit::Normal,
"默认值",
&ok);
if (ok && !text.isEmpty()) {
qDebug() << "输入的姓名:" << text;
}
// 整数输入
int age = QInputDialog::getInt(this, "年龄输入",
"请输入年龄:",
18, // 默认值
1, // 最小值
150, // 最大值
1, // 步长
&ok);
if (ok) {
qDebug() << "年龄:" << age;
}
// 浮点数输入
double price = QInputDialog::getDouble(this, "价格输入",
"请输入价格:",
99.99, // 默认值
0, // 最小值
9999, // 最大值
2, // 小数位数
&ok);
// 下拉选择
QStringList items = {"北京", "上海", "广州", "深圳"};
QString city = QInputDialog::getItem(this, "选择城市",
"请选择所在城市:",
items,
0, // 当前选中项索引
false, // 是否可编辑
&ok);
// 多行文本输入
QString comments = QInputDialog::getMultiLineText(this, "输入备注",
"请输入备注信息:",
"默认备注内容",
&ok);
视觉效果:
┌─────────────────────────────────────┐ │ 输入姓名 [×] │ ├─────────────────────────────────────┤ │ 请输入您的姓名: │ │ ┌─────────────────────────────┐ │ │ │ 张三 │ │ │ └─────────────────────────────┘ │ │ │ │ [取消] [确定] │ └─────────────────────────────────────┘ ┌─────────────────────────────────────┐ │ 选择城市 [×] │ ├─────────────────────────────────────┤ │ 请选择所在城市: │ │ ┌─────────────────────────────┐ │ │ │ 北京 ▼ │ │ │ └─────────────────────────────┘ │ │ │ │ [取消] [确定] │ └─────────────────────────────────────┘
4.2 实际应用场景
// PDF工具箱中的实际使用
void MainWindow::onSplitButtonClicked()
{
int pageCount = pdfCore->getPageCount(currentFiles.first());
bool ok;
QString rangeStr = QInputDialog::getText(this, "分割PDF",
QString("页码范围(如: 1-5,6-10,11-15)\n总页数: %1").arg(pageCount),
QLineEdit::Normal,
"1-10",
&ok);
if (!ok || rangeStr.isEmpty()) {
return; // 用户取消了
}
// 解析并执行分割...
}
void MainWindow::onCompressButtonClicked()
{
bool ok;
int quality = QInputDialog::getInt(this, "压缩PDF",
"压缩质量 (1-100):\n值越小文件越小,质量越低",
70,
1,
100,
10,
&ok);
if (ok) {
// 执行压缩...
}
}
五、颜色和字体对话框
5.1 QColorDialog(颜色选择)
#include <QColorDialog>
// 选择颜色
QColor color = QColorDialog::getColor(Qt::white, this, "选择颜色");
if (color.isValid()) {
// 应用颜色
label->setStyleSheet(QString("color: %1").arg(color.name()));
qDebug() << "选择的颜色:" << color.name(); // #RRGGBB格式
qDebug() << "RGB:" << color.red() << color.green() << color.blue();
}
// 高级用法
QColorDialog dialog(this);
dialog.setCurrentColor(Qt::blue);
dialog.setOptions(QColorDialog::ShowAlphaChannel); // 显示透明度
if (dialog.exec()) {
QColor color = dialog.currentColor();
// 使用颜色...
}
5.2 QFontDialog(字体选择)
#include <QFontDialog>
// 选择字体
bool ok;
QFont font = QFontDialog::getFont(&ok, QFont("微软雅黑", 12), this, "选择字体");
if (ok) {
textEdit->setFont(font);
qDebug() << "字体:" << font.family() << "大小:" << font.pointSize();
}
// 高级用法
QFontDialog dialog(this);
dialog.setCurrentFont(QFont("Consolas", 14));
dialog.setOptions(QFontDialog::MonospacedFonts); // 只显示等宽字体
if (dialog.exec()) {
QFont font = dialog.currentFont();
// 应用字体...
}
六、进度对话框
6.1 QProgressDialog(带取消的进度条)
#include <QProgressDialog>
void longRunningOperation()
{
int totalSteps = 100;
QProgressDialog progress("正在处理...", "取消", 0, totalSteps, this);
progress.setWindowTitle("进度");
progress.setWindowModality(Qt::WindowModal); // 模态
progress.setMinimumDuration(0); // 立即显示
progress.setValue(0);
for (int i = 0; i <= totalSteps; i++) {
if (progress.wasCanceled()) {
// 用户取消了操作
QMessageBox::information(this, "提示", "操作已取消");
break;
}
// 执行耗时操作
doWork(i);
// 更新进度
progress.setValue(i);
progress.setLabelText(QString("正在处理... %1%").arg(i));
// 让界面保持响应
QCoreApplication::processEvents();
}
progress.setValue(totalSteps);
}
6.2 自定义进度对话框
// 实际项目中更优雅的进度处理方式
class ProgressHelper : public QObject
{
Q_OBJECT
public:
ProgressHelper(QWidget *parent = nullptr) : QObject(parent)
{
m_progress = new QProgressDialog("正在处理...", "取消", 0, 100, parent);
m_progress->setWindowTitle("进度");
m_progress->setWindowModality(Qt::WindowModal);
m_progress->setMinimumDuration(0);
m_progress->setAutoClose(false); // 完成后不自动关闭
m_progress->setAutoReset(false);
}
bool isCanceled() const { return m_progress->wasCanceled(); }
void setRange(int min, int max) {
m_progress->setRange(min, max);
}
void setValue(int value) {
m_progress->setValue(value);
QCoreApplication::processEvents();
}
void setText(const QString &text) {
m_progress->setLabelText(text);
}
void finish() {
m_progress->setValue(m_progress->maximum());
m_progress->close();
}
private:
QProgressDialog *m_progress;
};
七、自定义对话框
7.1 创建自定义对话框类
// aboutdialog.h
#ifndef ABOUTDIALOG_H
#define ABOUTDIALOG_H
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
class AboutDialog : public QDialog
{
Q_OBJECT
public:
explicit AboutDialog(QWidget *parent = nullptr);
private:
QLabel *m_titleLabel;
QLabel *m_versionLabel;
QLabel *m_descriptionLabel;
QPushButton *m_closeButton;
};
#endif
// aboutdialog.cpp
#include "aboutdialog.h"
AboutDialog::AboutDialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle("关于");
setFixedSize(400, 300);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
// 创建控件
m_titleLabel = new QLabel("PDF全能工具箱");
QFont titleFont = m_titleLabel->font();
titleFont.setPointSize(18);
titleFont.setBold(true);
m_titleLabel->setFont(titleFont);
m_titleLabel->setAlignment(Qt::AlignCenter);
m_versionLabel = new QLabel("版本 1.0.0");
m_versionLabel->setAlignment(Qt::AlignCenter);
m_descriptionLabel = new QLabel(
"一款完全免费的PDF处理工具\n\n"
"功能:\n"
"• 合并/分割PDF\n"
"• 提取/旋转页面\n"
"• 插入/删除页面\n"
"• 压缩/加密/解密\n\n"
"基于Qt和qpdf开发\n"
"版权所有 © 2026"
);
m_descriptionLabel->setAlignment(Qt::AlignCenter);
m_descriptionLabel->setWordWrap(true);
m_closeButton = new QPushButton("关闭");
// 布局
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(m_titleLabel);
layout->addWidget(m_versionLabel);
layout->addSpacing(20);
layout->addWidget(m_descriptionLabel);
layout->addSpacing(20);
layout->addWidget(m_closeButton);
// 连接信号
connect(m_closeButton, &QPushButton::clicked, this, &QDialog::accept);
}
7.2 更复杂的自定义对话框
// inputdialog.h - 获取用户名和密码的自定义对话框
class LoginDialog : public QDialog
{
Q_OBJECT
public:
explicit LoginDialog(QWidget *parent = nullptr);
QString getUsername() const { return m_usernameEdit->text(); }
QString getPassword() const { return m_passwordEdit->text(); }
private:
QLineEdit *m_usernameEdit;
QLineEdit *m_passwordEdit;
QPushButton *m_loginButton;
QPushButton *m_cancelButton;
};
// inputdialog.cpp
LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
setWindowTitle("登录");
setFixedSize(350, 200);
setModal(true);
// 创建控件
QLabel *usernameLabel = new QLabel("用户名:");
QLabel *passwordLabel = new QLabel("密码:");
m_usernameEdit = new QLineEdit;
m_usernameEdit->setPlaceholderText("请输入用户名");
m_passwordEdit = new QLineEdit;
m_passwordEdit->setEchoMode(QLineEdit::Password);
m_passwordEdit->setPlaceholderText("请输入密码");
m_loginButton = new QPushButton("登录");
m_loginButton->setDefault(true); // 回车键触发
m_cancelButton = new QPushButton("取消");
// 布局
QFormLayout *formLayout = new QFormLayout;
formLayout->addRow(usernameLabel, m_usernameEdit);
formLayout->addRow(passwordLabel, m_passwordEdit);
QHBoxLayout *buttonLayout = new QHBoxLayout;
buttonLayout->addStretch();
buttonLayout->addWidget(m_loginButton);
buttonLayout->addWidget(m_cancelButton);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->addLayout(formLayout);
mainLayout->addLayout(buttonLayout);
// 信号连接
connect(m_loginButton, &QPushButton::clicked, this, &QDialog::accept);
connect(m_cancelButton, &QPushButton::clicked, this, &QDialog::reject);
// 输入验证:用户名和密码不能为空
auto validate = [this]() {
bool ok = !m_usernameEdit->text().isEmpty() &&
!m_passwordEdit->text().isEmpty();
m_loginButton->setEnabled(ok);
};
connect(m_usernameEdit, &QLineEdit::textChanged, validate);
connect(m_passwordEdit, &QLineEdit::textChanged, validate);
validate(); // 初始状态
}
// 使用
void MainWindow::onLogin()
{
LoginDialog dialog(this);
if (dialog.exec() == QDialog::Accepted) {
QString username = dialog.getUsername();
QString password = dialog.getPassword();
// 处理登录逻辑...
qDebug() << "登录用户名:" << username;
}
}
八、向导对话框
8.1 使用QWizard创建安装向导
#include <QWizard>
#include <QWizardPage>
// 第一个页面:欢迎页
class WelcomePage : public QWizardPage
{
public:
WelcomePage(QWidget *parent = nullptr) : QWizardPage(parent)
{
setTitle("欢迎使用PDF工具箱");
QLabel *label = new QLabel(
"本向导将帮助您完成PDF工具箱的安装。\n\n"
"PDF工具箱是一款免费的PDF处理工具,"
"支持合并、分割、压缩、加密等功能。\n\n"
"点击「下一步」继续。"
);
label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(label);
}
};
// 第二个页面:安装路径选择
class InstallPathPage : public QWizardPage
{
public:
InstallPathPage(QWidget *parent = nullptr) : QWizardPage(parent)
{
setTitle("选择安装路径");
m_pathEdit = new QLineEdit;
m_pathEdit->setText("C:/Program Files/PDFToolbox");
QPushButton *browseBtn = new QPushButton("浏览...");
QHBoxLayout *pathLayout = new QHBoxLayout;
pathLayout->addWidget(m_pathEdit);
pathLayout->addWidget(browseBtn);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(new QLabel("请选择安装目录:"));
layout->addLayout(pathLayout);
registerField("installPath*", m_pathEdit); // *表示必填
connect(browseBtn, &QPushButton::clicked, this, &InstallPathPage::browse);
}
QString getInstallPath() const { return m_pathEdit->text(); }
private:
void browse()
{
QString dir = QFileDialog::getExistingDirectory(this, "选择安装目录",
m_pathEdit->text());
if (!dir.isEmpty()) {
m_pathEdit->setText(dir);
}
}
QLineEdit *m_pathEdit;
};
// 第三个页面:组件选择
class ComponentsPage : public QWizardPage
{
public:
ComponentsPage(QWidget *parent = nullptr) : QWizardPage(parent)
{
setTitle("选择组件");
m_coreCheck = new QCheckBox("核心程序(必需)");
m_coreCheck->setChecked(true);
m_coreCheck->setEnabled(false);
m_shortcutCheck = new QCheckBox("创建桌面快捷方式");
m_shortcutCheck->setChecked(true);
m_startMenuCheck = new QCheckBox("添加到开始菜单");
m_startMenuCheck->setChecked(true);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(new QLabel("请选择要安装的组件:"));
layout->addWidget(m_coreCheck);
layout->addWidget(m_shortcutCheck);
layout->addWidget(m_startMenuCheck);
layout->addStretch();
registerField("createShortcut", m_shortcutCheck);
registerField("addToStartMenu", m_startMenuCheck);
}
private:
QCheckBox *m_coreCheck;
QCheckBox *m_shortcutCheck;
QCheckBox *m_startMenuCheck;
};
// 第四个页面:完成页
class FinishPage : public QWizardPage
{
public:
FinishPage(QWidget *parent = nullptr) : QWizardPage(parent)
{
setTitle("安装完成");
QLabel *label = new QLabel(
"PDF工具箱已成功安装!\n\n"
"点击「完成」退出安装向导。"
);
label->setWordWrap(true);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(label);
}
};
// 创建向导
void showInstallWizard()
{
QWizard wizard;
wizard.setWindowTitle("PDF工具箱安装向导");
wizard.setWizardStyle(QWizard::ModernStyle);
wizard.addPage(new WelcomePage);
wizard.addPage(new InstallPathPage);
wizard.addPage(new ComponentsPage);
wizard.addPage(new FinishPage);
if (wizard.exec() == QWizard::Accepted) {
// 获取用户选择
QString installPath = wizard.field("installPath").toString();
bool createShortcut = wizard.field("createShortcut").toBool();
bool addToStartMenu = wizard.field("addToStartMenu").toBool();
qDebug() << "安装路径:" << installPath;
qDebug() << "创建快捷方式:" << createShortcut;
qDebug() << "添加到开始菜单:" << addToStartMenu;
// 执行安装逻辑...
}
}
九、对话框最佳实践
9.1 内存管理
// 模态对话框:可以栈上创建
{
QMessageBox::information(this, "提示", "消息");
}
// 非模态对话框:堆上创建,设置关闭时删除
QDialog *dialog = new QDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
// 或者使用智能指针
std::unique_ptr<QDialog> dialog(new QDialog(this));
dialog->show();
9.2 中心位置设置
void showDialogCentered(QDialog *dialog)
{
// 移动到父窗口中心
if (dialog->parentWidget()) {
int x = dialog->parentWidget()->x() +
(dialog->parentWidget()->width() - dialog->width()) / 2;
int y = dialog->parentWidget()->y() +
(dialog->parentWidget()->height() - dialog->height()) / 2;
dialog->move(x, y);
}
dialog->show();
}
9.3 防止多个对话框
class MainWindow : public QMainWindow
{
private:
QDialog *m_settingsDialog = nullptr;
void showSettings()
{
// 避免重复创建
if (m_settingsDialog && m_settingsDialog->isVisible()) {
m_settingsDialog->raise();
m_settingsDialog->activateWindow();
return;
}
m_settingsDialog = new SettingsDialog(this);
m_settingsDialog->setAttribute(Qt::WA_DeleteOnClose);
m_settingsDialog->show();
}
};
十、本课小结
通过本篇学习,你掌握了:
✅ 标准消息对话框(QMessageBox)
✅ 文件对话框(QFileDialog)
✅ 输入对话框(QInputDialog)
✅ 颜色和字体对话框
✅ 进度对话框(QProgressDialog)
✅ 自定义对话框的创建
✅ 向导对话框(QWizard)
下一课预告:
第7篇「QProcess调用外部程序」——我们将学习如何在Qt程序中调用外部命令行程序,获取输出,并实现PDF工具箱背后的qpdf调用!
系列进度
| 状态 | 篇数 | 文章标题 |
|---|---|---|
| ✅ 已完成 | 第1篇 | Qt环境搭建与第一个Hello World |
| ✅ 已完成 | 第2篇 | Qt信号槽机制详解 |
| ✅ 已完成 | 第3篇 | Qt布局管理器完全指南 |
| ✅ 已完成 | 第4篇 | Qt样式表QSS美化教程 |
| ✅ 已完成 | 第5篇 | Qt常用控件全解析 |
| ✅ 已完成 | 第6篇 | Qt对话框系统 |
| 🔜 待发布 | 第7篇 | QProcess调用外部程序 |
如果觉得有用,欢迎点赞、收藏、关注!
下期见!👋
更多推荐


所有评论(0)