2026/4/6 15:08:36
网站建设
项目流程
对话框1. 对话框简介对话框Dialog 是一种弹出式窗口用于与用户进行交互传递信息或获取用户输入。在 Qt 中对话框广泛用于提示信息、获取输入、设置选项等。●模态对话框Modal Dialog在显示期间禁止用户与其他窗口进行交互用户必须先关闭对话框才能操作主窗口。●非模态对话框Non-Modal Dialog允许用户在对话框显示的同时与其他窗口进行交互。2. 对话框类型模态对话框●QMessageBox用于显示信息、警告、错误或提问等消息。●QInputDialog用于获取用户输入如文本、数字等。●QFileDialog: 用于打开文件●QProgressDialog: 进度对话框用来显示进度●QDialog用于创建自定义的对话框。非模态对话框可以使用show()方法显示非模态对话框与主窗口同时存在且可交互。3. 常用对话框类1 QMessageBoxQMessageBox提供了标准的对话框用于显示信息、警告、错误和提问。常用方法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构造函数里调整大小并且增加垂直布局将四个按钮加入布局中并且链接点击信号和槽函数在槽函数里弹出不同的消息框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 QInputDialogQInputDialog用于获取用户输入可以是文本、整数或浮点数。常用方法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里继续添加一个按钮提示输入姓名//创建一个输入对话框按钮 QPushButton *inputButton new QPushButton(输入姓名, this); layout-addWidget(inputButton);然后编写槽函数在槽函数中弹出一个输入对话框//响应输入框按钮被点击 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的构造函数中设置密码输入框的模式为不可见SetDialog::SetDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SetDialog) { ui-setupUi(this); //设置密码输入框模式 ui-passwdEdit-setEchoMode(QLineEdit::Password); }我们为SetDialog增加两个方法获取输入框里填写的名字和密码信息QString SetDialog::getUserName() const { return ui-nameEdit-text(); } QString SetDialog::getPassword() const { return ui-passwdEdit-text(); }接下来我们在MainWindow中添加一个按钮提示用户点击进而显示这个设置对话框QPushButton *openDialogButton new QPushButton(打开设置对话框, this); layout-addWidget(openDialogButton);然后链接按钮点击信号当按钮被点击后显示对话框对话框展示可以使用exec()方法展示后对话框会阻塞用户其他操作只能点击确定或者取消点击确定或者取消后exec()会返回QDialog::Accept或者QDialog::Rejected.如果点击的是确定则弹出用户输入的信息//链接点击信号 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()方法显示调用该方法后程序会等待对话框关闭后继续执行。QDialog dialog; dialog.exec(); // 模态非模态对话框使用show()方法显示对话框显示后程序继续执行不会等待对话框关闭。QDialog *dialog new QDialog(this); dialog-show(); // 非模态2 模态与非模态对话框的区别模态对话框阻塞主窗口用户必须先关闭对话框才能返回主窗口。常用于需要强制用户响应的情况如确认操作、输入关键信息等。非模态对话框不阻塞主窗口用户可以在对话框和主窗口之间自由切换。常用于辅助信息显示、工具窗口等。扩展1 对话框事件过滤在我们使用其他厂商的应用的时候经常遇到这样一个场景点击关闭窗口后会弹出提示框提示是否确认关闭如果点击取消则不关闭对话框。点击确认才关闭对话框。怎么实现上述功能呢开发思路1 先重写对话框的关闭事件处理函数closeEvent, 这个函数有个参数QCloseEvent表示关闭事件void closeEvent(QCloseEvent *) override;对于关闭事件继承自QEventQEvent提供了两个方法//表示接受 inline void accept() { m_accept true; } //表示忽略 inline void ignore() { m_accept false; }如果我们把这个事件忽略他就不会被事件轮询处理。如果我们接受这个事件那么他就会被事件轮询处理所以给出关闭处理的完美答案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 QFileDialogQT为了方便我们操作提供了很多快速创建不同类型对话框的类以及静态方法比如文件对话框常见用途打开文件如文本文件、图片等保存文件选择目录常用方法静态函数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打开单个文件#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保存文件#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选择多个文件#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选择目录#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中示例代码#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中添加按钮并响应点击信号//图像浏览器 //创建按钮提示用户打开对话框 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(); });运行程序点击按钮后可实现上述效果。QProgressDialogQProgressDialog是 Qt 提供的一个对话框类用于显示长时间运行任务的进度。它可以显示任务的进度条、标签信息以及一个“取消”按钮允许用户中断任务。常见用途下载或上传文件数据处理或转换文件复制或移动常用方法构造函数QProgressDialog(QWidget *parent nullptr, Qt::WindowFlags flags Qt::WindowFlags())或者指定详细信息QProgressDialog(const QString labelText, const QString cancelButtonText, int minimum, int maximum, QWidget *parent nullptr, Qt::WindowFlags flags Qt::WindowFlags())设置文本void setLabelText(const QString label); void setCancelButtonText(const QString text);范围和值void setRange(int minimum, int maximum); void setValue(int value);或者使用单一参数设置进度范围void setMaximum(int maximum); void setMinimum(int minimum);其他设置void setWindowModality(Qt::WindowModality modality); void setAutoClose(bool autoClose); void setAutoReset(bool autoReset);信号void canceled(): 当用户点击“取消”按钮时发出。示例代码示例 1模拟一个耗时任务实现如下图效果我们可以在main函数中新增按钮和点击的响应逻辑//创建一个按钮演示进度框 //创建按钮提示用户打开对话框 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, 完成, 任务已完成。); } });