欢迎光临
我们一直在努力

【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)
未经允许不得转载:171主机测评 » 【Qt/C++ 桌面开发实战营】第6篇:Qt对话框系统
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址