对话框
- 对话框简介
对话框(Dialog) 是一种弹出式窗口,用于与用户进行交互,传递信息或获取用户输入。在 Qt 中,对话框广泛用于提示信息、获取输入、设置选项等。
●模态对话框(Modal Dialog):在显示期间,禁止用户与其他窗口进行交互,用户必须先关闭对话框才能操作主窗口。
●非模态对话框(Non-Modal Dialog):允许用户在对话框显示的同时,与其他窗口进行交互。
- 对话框类型
模态对话框
●QMessageBox:用于显示信息、警告、错误或提问等消息。
●QInputDialog:用于获取用户输入,如文本、数字等。
●QFileDialog: 用于打开文件
●QProgressDialog: 进度对话框,用来显示进度
●QDialog:用于创建自定义的对话框。
非模态对话框
可以使用 show() 方法显示非模态对话框,与主窗口同时存在且可交互。
3. 常用对话框类
1 QMessageBox
QMessageBox 提供了标准的对话框用于显示信息、警告、错误和提问。
常用方法:
information(QWidget *parent, const QString &title, const QString &text, ...)warning(QWidget *parent, const QString &title, const QString &text, ...)critical(QWidget *parent, const QString &title, const QString &text, ...)question(QWidget *parent, const QString &title, const QString &text, ...)
案例
创建一个MainWindow,在MainWindow里添加几个按钮,每个按钮点击后显示不同的QMessageBox,比如按下了警告按钮,就弹出警告信息。如下图

开发思路
在MainWindow构造函数里调整大小,并且增加垂直布局,将四个按钮加入布局中,并且链接点击信号和槽函数,在槽函数里弹出不同的消息框
cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//重置大小
this->resize(600,400);
//设置中心部件
QWidget *centralWidget = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
//创建按钮点击后响应基本信息
QPushButton * infoBtn = new QPushButton("显示信息对话框", this);
layout->addWidget(infoBtn);
//创建警告信息
QPushButton * warnBtn = new QPushButton("显示警告对话框", this);
layout->addWidget(warnBtn);
//创建危机信息
QPushButton * criticalBtn = new QPushButton("显示危机对话框", this);
layout->addWidget(criticalBtn);
//创建提问信息
QPushButton * questionBtn = new QPushButton("显示提问对话框", this);
layout->addWidget(questionBtn);
setCentralWidget(centralWidget);
// 响应信息按钮
connect(infoBtn, &QPushButton::clicked, this, [=]() {
//弹出信息对话框
QMessageBox::information(this, "信息", "这是一个信息对话框");
});
//响应警告按钮被点击
connect(warnBtn, &QPushButton::clicked, this, [=]() {
//弹出警告对话框
QMessageBox::warning(this, "警告", "这是一个警告对话框");
});
//响应危机按钮被点击
connect(criticalBtn, &QPushButton::clicked, this, [=]() {
//弹出警告对话框
QMessageBox::critical(this, "危机", "这是一个危机对话框");
});
//响应提问按钮被点击
connect(questionBtn, &QPushButton::clicked, this, [=]() {
//弹出警告对话框
QMessageBox::question(this, "提问", "元神启动了吗?");
});
}
运行程序后,发现这些消息框如果不点击确定,会阻塞MainWindow。
2 QInputDialog
QInputDialog 用于获取用户输入,可以是文本、整数或浮点数。
常用方法:
getText(QWidget *parent, const QString &title, const QString &label, ...)getInt(QWidget *parent, const QString &title, const QString &label, ...)getDouble(QWidget *parent, const QString &title, const QString &label, ...)
案例练习:
我们需实现如下界面,点击输入姓名按钮后弹出输入对话框

我们在MainWindow里继续添加一个按钮,提示输入姓名
cpp
//创建一个输入对话框按钮
QPushButton *inputButton = new QPushButton("输入姓名", this);
layout->addWidget(inputButton);
然后编写槽函数,在槽函数中弹出一个输入对话框
cpp
//响应输入框按钮被点击
connect(inputButton, &QPushButton::clicked, this, [=]() {
bool ok;
//弹出输入对话框
QString name = QInputDialog::getText(this,
"输入", "请输入你的姓名:",
QLineEdit::Normal, "", &ok);
//返回ok为true表示创建成功,name不为空则弹出信息框
if (ok && !name.isEmpty()) {
QMessageBox::information(this, "姓名", QString("你好,%1!").arg(name));
}
});
3 QDialog(自定义对话框)
QDialog 是一个基类,用于创建自定义的对话框,可以通过 Qt Designer 设计界面,并添加自定义功能。
界面如下

点击ok后弹出提示框

创建自定义对话框的步骤:
- 设计界面:
-
- 使用 Qt Designer 创建一个新的对话框(.ui 文件)。
- 添加需要的控件(如标签、输入框、按钮等)。
- 创建对话框类:
-
- 使用
QDialog作为基类。 - 在类中包含生成的 UI 类。
- 实现对话框的功能,如接受用户输入、验证输入、信号与槽等。
- 使用
开发思路:
我们创建一个简单的设置对话框,用户可以输入用户名和密码。右键项目选择新建设计师界面类

选择界面模板,创建一个Dialog带按钮组,按钮组在下方的界面

点击下一步,创建的Dialog名字为SetDialog
拖动两个水平布局放入SetDialog中,再将SetDialog设置为垂直布局

右侧布局管理器修改属性名

我们在SetDialog的构造函数中设置密码输入框的模式为不可见
cpp
SetDialog::SetDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SetDialog)
{
ui->setupUi(this);
//设置密码输入框模式
ui->passwdEdit->setEchoMode(QLineEdit::Password);
}
我们为SetDialog增加两个方法,获取输入框里填写的名字和密码信息
cpp
QString SetDialog::getUserName() const
{
return ui->nameEdit->text();
}
QString SetDialog::getPassword() const
{
return ui->passwdEdit->text();
}
接下来我们在MainWindow中添加一个按钮,提示用户点击,进而显示这个设置对话框
cpp
QPushButton *openDialogButton = new QPushButton("打开设置对话框", this);
layout->addWidget(openDialogButton);
然后链接按钮点击信号,当按钮被点击后,显示对话框,对话框展示可以使用exec()方法,展示后对话框会阻塞用户其他操作,只能点击确定或者取消,
点击确定或者取消后,exec()会返回QDialog::Accept或者QDialog::Rejected.
如果点击的是确定,则弹出用户输入的信息
cpp
//链接点击信号
connect(openDialogButton, &QPushButton::clicked, this, [=]() {
//创建设置对话框
SetDialog dialog(this);
//exec表示模态方式启动
if (dialog.exec() == QDialog::Accepted) {
QString userName = dialog.getUserName();
QString password = dialog.getPassword();
QMessageBox::information(this, "设置",
QString("用户名:%1\n密码:%2").arg(userName, password));
}
});
运行程序,点击打开设置对话框按钮,会触发槽函数,显示对话框,只有点击ok或者cancel之后,对话框才会退出,否则一直阻塞。
4. 对话框的实现与使用
1 创建和显示对话框
- 模态对话框 :使用
exec()方法显示,调用该方法后,程序会等待对话框关闭后继续执行。
cpp
QDialog dialog;
dialog.exec(); // 模态
- 非模态对话框 :使用
show()方法显示,对话框显示后,程序继续执行,不会等待对话框关闭。
cpp
QDialog *dialog = new QDialog(this);
dialog->show(); // 非模态
2 模态与非模态对话框的区别
- 模态对话框:
-
- 阻塞主窗口,用户必须先关闭对话框才能返回主窗口。
- 常用于需要强制用户响应的情况,如确认操作、输入关键信息等。
- 非模态对话框:
-
- 不阻塞主窗口,用户可以在对话框和主窗口之间自由切换。
- 常用于辅助信息显示、工具窗口等。
扩展
1 对话框事件过滤
在我们使用其他厂商的应用的时候,经常遇到这样一个场景
点击关闭窗口后会弹出提示框,提示是否确认关闭,如果点击取消,则不关闭对话框。
点击确认才关闭对话框。

怎么实现上述功能呢?
开发思路
1 先重写对话框的关闭事件处理函数closeEvent, 这个函数有个参数QCloseEvent,表示关闭事件
cpp
void closeEvent(QCloseEvent *) override;
对于关闭事件继承自QEvent,QEvent提供了两个方法
cpp
//表示接受
inline void accept() { m_accept = true; }
//表示忽略
inline void ignore() { m_accept = false; }
如果我们把这个事件忽略,他就不会被事件轮询处理。如果我们接受这个事件,那么他就会被事件轮询处理,所以给出关闭处理的完美答案
cpp
void closeEvent(QCloseEvent *event) {
QMessageBox::StandardButton resBtn = QMessageBox::question(this, "关闭确认",
tr("你确定要关闭对话框吗?\n"),
QMessageBox::No | QMessageBox::Yes,
QMessageBox::Yes);
if (resBtn != QMessageBox::Yes) {
event->ignore();
} else {
event->accept();
}
}
2 QFileDialog
QT为了方便我们操作,提供了很多快速创建不同类型对话框的类,以及静态方法,比如文件对话框
常见用途:
- 打开文件(如文本文件、图片等)
- 保存文件
- 选择目录
常用方法
静态函数:
static QString getOpenFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, Options options = Options())
打开一个"打开文件"对话框,允许用户选择单个文件。
static QStringList getOpenFileNames(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, Options options = Options())
打开一个"打开文件"对话框,允许用户选择多个文件。
static QString getSaveFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, Options options = Options())
打开一个"保存文件"对话框,允许用户选择或输入要保存的文件名。
static QString getExistingDirectory(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), Options options = Options())
打开一个"选择目录"对话框,允许用户选择一个现有的目录。
示例代码
示例 1:打开单个文件
cpp
#include <QApplication>
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton button("打开文件");
button.resize(200, 50);
button.show();
QObject::connect(&button, &QPushButton::clicked, [&]() {
QString fileName = QFileDialog::getOpenFileName(
&button,
"选择一个文件",
"/home",
"所有文件 (*.*);;文本文件 (*.txt);;图片文件 (*.png *.jpg *.bmp)");
if (!fileName.isEmpty()) {
QMessageBox::information(&button, "文件选择", QString("你选择了:\n%1").arg(fileName));
}
});
return a.exec();
}
示例 2:保存文件
cpp
#include <QApplication>
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton button("保存文件");
button.resize(200, 50);
button.show();
QObject::connect(&button, &QPushButton::clicked, [&]() {
QString fileName = QFileDialog::getSaveFileName(
&button,
"保存文件",
"/home/untitled.txt",
"文本文件 (*.txt);;所有文件 (*.*)");
if (!fileName.isEmpty()) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out << "这是测试保存的文件内容。\n";
file.close();
QMessageBox::information(&button, "保存文件", "文件已成功保存。");
} else {
QMessageBox::warning(&button, "保存文件", "无法打开文件进行写入。");
}
}
});
return a.exec();
}
示例 3:选择多个文件
cpp
#include <QApplication>
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton button("选择多个文件");
button.resize(200, 50);
button.show();
QObject::connect(&button, &QPushButton::clicked, [&]() {
QStringList fileNames = QFileDialog::getOpenFileNames(
&button,
"选择多个文件",
"/home",
"所有文件 (*.*);;图片文件 (*.png *.jpg *.bmp);;文本文件 (*.txt)");
if (!fileNames.isEmpty()) {
QString files = fileNames.join("\n");
QMessageBox::information(&button, "文件选择", QString("你选择了:\n%1").arg(files));
}
});
return a.exec();
}
示例 4:选择目录
cpp
#include <QApplication>
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton button("选择目录");
button.resize(200, 50);
button.show();
QObject::connect(&button, &QPushButton::clicked, [&]() {
QString dir = QFileDialog::getExistingDirectory(
&button,
"选择一个目录",
"/home",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!dir.isEmpty()) {
QMessageBox::information(&button, "目录选择", QString("你选择了目录:\n%1").arg(dir));
}
});
return a.exec();
}
实际案例
案例:图像浏览器
创建一个简单的图像浏览器,允许用户选择一个目录,显示该目录中的所有图片文件。

选择文件夹后,会将选择文件夹内的所有图片展开,点击左侧列表内容,会在右侧显示图片

步骤概述:
- 创建主窗口,包含:
-
- 一个按钮"选择目录"
- 一个
QListWidget显示图片列表 - 一个
QLabel显示选中的图片
- 实现功能:
-
- 点击按钮时,弹出
QFileDialog选择目录 - 扫描目录中的图片文件,并在
QListWidget中显示 - 选择列表中的图片时,显示在
QLabel中
- 点击按钮时,弹出
示例代码:
cpp
#include <QPushButton>
#include <QFileDialog>
#include <QListWidget>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPixmap>
#include <QMessageBox>
#include <QDebug>
class ImageBrowser : public QDialog
{
Q_OBJECT
public:
ImageBrowser(QWidget *parent = nullptr) : QDialog(parent)
{
QPushButton *button = new QPushButton("选择目录", this);
listWidget = new QListWidget(this);
auto *right_wid = new QWidget(this);
auto *right_layout = new QVBoxLayout(right_wid);
imageLabel = new QLabel(this);
imageLabel->setFixedSize(400,400);
right_layout->addWidget(imageLabel);
QHBoxLayout *mainLayout = new QHBoxLayout(this);
QVBoxLayout *leftLayout = new QVBoxLayout();
leftLayout->addWidget(button);
leftLayout->addWidget(listWidget);
mainLayout->addLayout(leftLayout);
mainLayout->addWidget(right_wid);
connect(button, &QPushButton::clicked, this, &ImageBrowser::selectDirectory);
connect(listWidget, &QListWidget::itemClicked, this, &ImageBrowser::displayImage);
}
~ImageBrowser(){
// QMessageBox::information(nullptr,"提示信息","图片浏览器析构");
}
private slots:
void selectDirectory()
{
_dir = QFileDialog::getExistingDirectory(
this,
"选择图片目录",
"/home",
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if (!_dir.isEmpty()) {
listWidget->clear();
QStringList filters;
filters << "*.png" << "*.jpg" << "*.jpeg" << "*.bmp" << "*.gif";
QDir directory(_dir);
QStringList images = directory.entryList(filters, QDir::Files);
for (const QString &image : images) {
listWidget->addItem(image);
}
}
}
void displayImage(QListWidgetItem *item)
{
QString imagePath = _dir + QDir::separator() + item->text();
QPixmap pixmap(imagePath);
if (!pixmap.isNull()) {
//保持横纵比,且平滑缩放,返回一个新的缩放后的图片
pixmap = pixmap.scaled(imageLabel->width(),imageLabel->height(),Qt::KeepAspectRatio,
Qt::SmoothTransformation);
imageLabel->setPixmap(pixmap);
}
}
private:
QListWidget *listWidget;
QLabel *imageLabel;
QString _dir;
};
mainwindow中添加按钮,并响应点击信号
cpp
//图像浏览器
//创建按钮提示用户打开对话框
QPushButton *openPicBtn = new QPushButton("打开图片浏览器", this);
layout->addWidget(openPicBtn);
//链接点击信号
connect(openPicBtn, &QPushButton::clicked, this, [=]() {
//创建浏览器
_browser = new ImageBrowser();
_browser->setWindowTitle("简单图像浏览器");
_browser->resize(600, 450);
_browser->exec();
_browser->deleteLater();
});
运行程序,点击按钮后可实现上述效果。
QProgressDialog
QProgressDialog 是 Qt 提供的一个对话框类,用于显示长时间运行任务的进度。它可以显示任务的进度条、标签信息,以及一个"取消"按钮,允许用户中断任务。
常见用途:
- 下载或上传文件
- 数据处理或转换
- 文件复制或移动
常用方法
- 构造函数:
cpp
QProgressDialog(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags())
或者指定详细信息:
cpp
QProgressDialog(const QString &labelText, const QString &cancelButtonText, int minimum, int maximum, QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags())
- 设置文本:
cpp
void setLabelText(const QString &label);
void setCancelButtonText(const QString &text);
- 范围和值:
cpp
void setRange(int minimum, int maximum);
void setValue(int value);
或者使用单一参数设置进度范围:
cpp
void setMaximum(int maximum);
void setMinimum(int minimum);
- 其他设置:
cpp
void setWindowModality(Qt::WindowModality modality);
void setAutoClose(bool autoClose);
void setAutoReset(bool autoReset);
- 信号:
-
void canceled(): 当用户点击"取消"按钮时发出。
示例代码
示例 1:模拟一个耗时任务
实现如下图效果

我们可以在main函数中新增按钮和点击的响应逻辑
cpp
//创建一个按钮演示进度框
//创建按钮提示用户打开对话框
QPushButton *progressBtn = new QPushButton("演示进度框", this);
layout->addWidget(progressBtn);
//链接点击信号
connect(progressBtn, &QPushButton::clicked, this, [=]() {
//演示进度框
QProgressDialog progress("正在执行任务...", "取消", 0, 100,this);
progress.setWindowModality(Qt::WindowModal);
progress.setMinimumDuration(0);
progress.setValue(0);
for (int i = 0; i <= 100; ++i) {
// 模拟耗时任务
// 暂停1秒
QEventLoop loop;//定义一个新的事件循环
QTimer::singleShot(1000, &loop, SLOT(quit()));//创建单次定时器,槽函数为事件循环的退出函数
loop.exec();//事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出
progress.setValue(i);
if (progress.wasCanceled()) {
QMessageBox::information(this, "取消", "任务已被取消。");
break;
}
}
if (progress.value() == progress.maximum()) {
QMessageBox::information(this, "完成", "任务已完成。");
}
});