Qt 对话框全家桶实战:模态 / 非模态 + 5 大内置对话框全攻略


🔥草莓熊Lotso: 个人主页
❄️个人专栏: 《C++知识分享》 《Linux 入门到实践:零基础也能懂》
✨生活是默默的坚持,毅力是永久的享受!


🎬 博主简介:


文章目录

  • 前言:
  • [一. 对话框核心概念:模态 vs 非模态 vs 混合模态](#一. 对话框核心概念:模态 vs 非模态 vs 混合模态)
    • [1.1 模态对话框(阻塞式)](#1.1 模态对话框(阻塞式))
    • [1.2 非模态对话框(非阻塞式)](#1.2 非模态对话框(非阻塞式))
    • [1.3 混合模态对话框(半阻塞式)](#1.3 混合模态对话框(半阻塞式))
  • [二. Qt 5 大内置标准对话框(直接复用,不用自定义)](#二. Qt 5 大内置标准对话框(直接复用,不用自定义))
    • [2.1 消息对话框(QMessageBox):应用最广的交互组件](#2.1 消息对话框(QMessageBox):应用最广的交互组件)
    • [2.2 颜色对话框(QColorDialog):可视化颜色选择](#2.2 颜色对话框(QColorDialog):可视化颜色选择)
    • [2.3 文件对话框(QFileDialog):文件打开 / 保存](#2.3 文件对话框(QFileDialog):文件打开 / 保存)
    • [2.4 字体对话框(QFontDialog):字体样式设置](#2.4 字体对话框(QFontDialog):字体样式设置)
    • [2.5 输入对话框(QInputDialog):临时数据输入](#2.5 输入对话框(QInputDialog):临时数据输入)
  • [三. 对话框开发避坑指南](#三. 对话框开发避坑指南)
  • 结尾:

前言:

对话框是 Qt 桌面应用中不可或缺的交互组件,专门用于处理短期任务或简洁交互(如消息提示、文件选择、参数输入)。Qt 不仅支持自定义对话框,还内置了 5 种高频实用的标准对话框(消息框、颜色选择、文件操作、字体设置、数据输入),同时提供模态、非模态、混合模态三种交互模式,覆盖绝大多数开发场景。本文逐一拆解对话框的分类、创建方法和 5 大内置对话框的实战用法,通过可直接运行的代码示例,帮你快速掌握 Qt 对话框的核心技巧,避免重复造轮子,提升开发效率。


一. 对话框核心概念:模态 vs 非模态 vs 混合模态

在使用对话框前,必须先明确其交互模式 ------ 不同模式决定了对话框与父窗口的交互关系,直接影响用户体验。Qt 中对话框主要分为三类,核心区别在于是否阻塞父窗口交互。

1.1 模态对话框(阻塞式)

  • 核心特性:对话框显示后,父窗口完全不可交互,必须关闭对话框才能回到父窗口,属于 "阻塞式" 交互;
  • 调用方式 :通过 QDialog::exec() 方法调用;
  • 适用场景:必须依赖用户选择的操作(如确认删除、文件保存、消息提示);
  • 代码示例:点击菜单 "新建" 弹出模态对话框:
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QAction>
#include <QMenu>
#include <QMenuBar>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
	ui->setupUi(this);
    // 创建菜单栏和菜单项
    QMenuBar *menuBar = this->menuBar();
    QMenu *fileMenu = new QMenu("文件", this);
    QAction *newAction = new QAction("新建", this);
    fileMenu->addAction(newAction);
    menuBar->addMenu(fileMenu);

    // 点击"新建"弹出模态对话框
    connect(newAction, &QAction::triggered, [=]() {
        QDialog dlg(this); // 栈上创建(模态对话框可在栈上,关闭后自动销毁)
        dlg.resize(300, 200);
        dlg.setWindowTitle("模态对话框");
        dlg.exec(); // 阻塞式调用,直到关闭对话框才返回
        qDebug() << "模态对话框已关闭";
    });
}

1.2 非模态对话框(非阻塞式)

  • 核心特性:对话框显示后,父窗口仍可正常交互,属于 "非阻塞式" 交互;
  • 调用方式 :通过 QDialog::show() 方法调用;
  • 关键注意 :必须在堆上创建(栈上创建会一闪而过),且需设置 Qt::WA_DeleteOnClose 属性,关闭时自动释放内存,避免泄漏;
  • 适用场景:辅助功能操作(如查找替换、属性设置、日志窗口);
  • 代码示例:点击菜单 "查找" 弹出非模态对话框:
cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QAction>
#include <QMenu>
#include <QMenuBar>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
	ui->setupUi(this);
    QMenuBar *menuBar = this->menuBar();
    QMenu *editMenu = new QMenu("编辑", this);
    QAction *findAction = new QAction("查找", this);
    editMenu->addAction(findAction);
    menuBar->addMenu(editMenu);

    // 点击"查找"弹出非模态对话框
    connect(findAction, &QAction::triggered, [=]() {
        // 堆上创建,设置父对象和自动销毁属性
        QDialog *dlg = new QDialog(this);
        dlg->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动释放内存
        dlg->resize(300, 200);
        dlg->setWindowTitle("非模态对话框");
        dlg->show(); // 非阻塞式调用,立即返回
        qDebug() << "非模态对话框已显示(不阻塞后续代码)";
    });
}

补充示例

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    QDialog* dialog = new QDialog(this);
    dialog->setWindowTitle("对话框");
    dialog->resize(400, 300);
    dialog->show(); // 展示对话框

    // 注意内存泄漏,Qt给我们提供了设置属性解决这个问题的方法
    dialog->setAttribute(Qt::WA_DeleteOnClose);
}

1.3 混合模态对话框(半阻塞式)

核心特性:兼具模态和非模态的优点 ------ 创建 / 销毁逻辑同非模态(堆上创建、自动销毁),功能上同模态(阻塞父窗口交互);

调用方式:QDialog::show() + setModal(true);

适用场景:需要阻塞父窗口,但希望对话框独立销毁的场景(如复杂参数配置);

代码示例:点击菜单 "配置" 弹出混合模态对话框:

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QAction>
#include <QMenu>
#include <QMenuBar>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
	ui->setupUi(this);
    QMenuBar *menuBar = this->menuBar();
    QMenu *settingMenu = new QMenu("设置", this);
    QAction *configAction = new QAction("配置", this);
    settingMenu->addAction(configAction);
    menuBar->addMenu(settingMenu);

    // 点击"配置"弹出混合模态对话框
    connect(configAction, &QAction::triggered, [=]() {
        QDialog *dlg = new QDialog(this);
        dlg->setAttribute(Qt::WA_DeleteOnClose); // 非模态的销毁逻辑
        dlg->setModal(true); // 模态的阻塞逻辑
        dlg->resize(300, 200);
        dlg->setWindowTitle("混合模态对话框");
        dlg->show(); // 非阻塞调用,但父窗口被阻塞
    });
}

三种模式核心对比:

模式 调用方法 创建位置 父窗口交互 适用场景
模态 exec() 栈 / 堆 阻塞 确认提示、文件保存
非模态 show() 不阻塞 查找替换、日志窗口
混合模态 show() + setModal(true) 阻塞 复杂参数配置

补充知识点: 自定义对话框的方式

这里就不详细介绍了,操作不好展示,大家感兴趣的话可以自己去研究一下,可以看看我的代码仓库中的对应代码(点击仓库即可跳转)


二. Qt 5 大内置标准对话框(直接复用,不用自定义)

Qt 内置了 5 种高频使用的标准对话框,无需手动布局,直接调用即可实现核心功能,覆盖 "消息提示、颜色选择、文件操作、字体设置、数据输入" 五大场景

2.1 消息对话框(QMessageBox):应用最广的交互组件

QMessageBox 用于显示消息提示或强制用户选择(如确认、取消、重试),支持 4 种预设类型(提问、信息、警告、错误),可自定义按钮和图标。
核心 API(静态方法,直接调用):

  • question():提问对话框(带问号图标,需用户选择);
  • information():信息对话框(带信息图标,提示通知);
  • warning():警告对话框(带警告图标,非致命错误);
  • critical():错误对话框(带错误图标,致命错误);
  • 通用参数parent(父窗口)、title(标题)、text(内容)、buttons(按钮组合)。

实战示例1:自己创建消息对话框

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QPushButton>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QMessageBox* message = new QMessageBox(this);
    message->setWindowTitle("对话框标题");
    message->setText("这是对话框文本");
    message->setIcon(QMessageBox::Warning);
    message->setStandardButtons(QMessageBox::Ok | QMessageBox::Save | QMessageBox::Cancel);

    // 添加自定义按钮,可以关联信号槽完成一些操作
    // QPushButton* button = new QPushButton("按钮", message);
    // message->addButton(button, QMessageBox::AcceptRole);

    // 非模态对话框,在窗口关闭之前会阻塞在这里
    // 我们点击按钮窗口关闭之后就可以通过exec的返回值,来知道用户点击的是那个按钮,然后去执行一些对应逻辑了
    int result = message->exec();
    if(result == QMessageBox::Ok){
        qDebug() << "OK";
    }else if(result == QMessageBox::Save){
        qDebug() << "Save";
    }else if(result == QMessageBox::Cancel){
        qDebug() << "Cancel";
    }

    message->setAttribute(Qt::WA_DeleteOnClose);
    // delete message; // 所以这样也可以
}


实战示例2:使用静态方法直接创建对胡话框

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    // 除了warning也还有其他几种
    int result = QMessageBox::warning(this, "对话框标题", "对话框文本", QMessageBox::Ok | QMessageBox::Cancel);
    if(result == QMessageBox::Ok){
        qDebug() << "Ok";
    }else if(result == QMessageBox::Cancel){
        qDebug() << "Cancel";
    }
}

关键注意点:

  • 按钮类型通过 QMessageBox::StandardButton 枚举指定(如 OkCancelYesNo);
  • 静态方法直接返回用户选择的按钮,无需手动绑定信号槽;
  • 图标会根据对话框类型自动匹配,无需额外设置。

2.2 颜色对话框(QColorDialog):可视化颜色选择

QColorDialog 用于让用户选择颜色,支持基础颜色、自定义颜色、屏幕取色,返回 QColor 对象(包含 RGB、HSV 等颜色信息)。
核心 API:

  • getColor():静态方法,直接弹出对话框并返回选中的颜色;
  • setCurrentColor():设置默认选中的颜色;
  • open():非模态打开对话框(需绑定 colorSelected 信号获取结果)。

实战示例:颜色选择并设置窗口背景

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QColorDialog>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QColor color = QColorDialog::getColor(QColor(0, 255, 0), this, "选择颜色");
    // 可以通过用户选择的颜色来修改窗口背景色
    // QString style = "background-color: rgb(" + QString::number(color.red()) + ", " + QString::number(color.green())
    //        + ", " + QString::number(color.blue()) + ");";


    char style[1024] = {0};
    sprintf(style, "background-color: rgb(%d, %d, %d)", color.red(), color.green(), color.blue());
    this->setStyleSheet(style);
}


2.3 文件对话框(QFileDialog):文件打开 / 保存

QFileDialog 是文件操作的核心对话框,支持单个文件打开、多个文件打开、文件保存,可设置默认路径和文件过滤器(如只显示 .txt.jpg 文件)。

核心 API(静态方法):

  • getOpenFileName():打开单个文件,返回文件路径字符串;
  • getOpenFileNames():打开多个文件,返回文件路径字符串列表;
  • getSaveFileName():保存文件,返回保存路径字符串;
  • 关键参数filter(文件过滤器,如 "文本文件 (*.txt);;所有文件 (*.*)")。

实战示例:文件对话框的基本演示

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

// 打开或者保存的功能还需要额外实现,这里先不讲
void MainWindow::on_pushButton_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this);
    qDebug() << filePath;

}

void MainWindow::on_pushButton_2_clicked()
{
    QString filePath = QFileDialog::getSaveFileName(this);
    qDebug() << filePath;
}



2.4 字体对话框(QFontDialog):字体样式设置

QFontDialog 用于让用户选择字体、字号、加粗、倾斜等样式,返回 QFont 对象,可直接应用到文本控件(如 QTextEditQLabel)。
核心 API:

  • getFont():静态方法,弹出对话框并返回选中的字体;
  • 第一个参数为 bool* 类型,用于接收用户是否确认选择(true = 确认,false = 取消)。

实战示例:设置文本字体

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFontDialog>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    bool ok;
    QFont font = QFontDialog::getFont(&ok);
    qDebug() << "ok = " << ok;
    // qDebug() << font;
    qDebug() << font.family();
    qDebug() << font.pointSize();
    qDebug() << font.bold();
    qDebug() << font.italic();

    // 将用户选择的字体相关属性设置到按钮上
    ui->pushButton->setFont(font);
}


2.5 输入对话框(QInputDialog):临时数据输入

QInputDialog 用于快速获取用户输入的临时数据,支持 3 种类型:整型、浮点型、字符串(含下拉选择),无需自定义输入界面。
核心 API(静态方法):

  • getInt():获取整型数据(支持设置范围和步长);
  • getDouble():获取浮点型数据(支持设置精度);
  • getItem():获取下拉列表中的字符串选择;
  • getText():获取自定义字符串输入。

实战示例:3 种输入类型完整用法

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QInputDialog>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    int result = QInputDialog::getInt(this, "整数输入对话框", "请输入一个整数: ");\
    qDebug() << result;
}



void MainWindow::on_pushButton_2_clicked()
{
    double result = QInputDialog::getDouble(this, "浮点输入对话框", "请输入一个浮点数: ");\
    qDebug() << result;
}

void MainWindow::on_pushButton_3_clicked()
{
    QStringList items;
    items.push_back("111");
    items.push_back("222");
    items.push_back("333");
    QString item = QInputDialog::getItem(this, "条目输入对话框", "请输入条目: ", items);
    qDebug() << item;
}



三. 对话框开发避坑指南

  • 非模态对话框必须堆上创建 :栈上创建会因局部变量生命周期结束而一闪而过,且需设置 Qt::WA_DeleteOnClose 避免内存泄漏;
  • 模态对话框可栈上创建exec() 阻塞期间,对话框不会被销毁,关闭后自动释放栈内存,更简洁;
  • 文件对话框路径分隔符 :Qt 支持 /\\,推荐使用 /(无需转义),如 "C:/Users/Desktop"
  • 颜色 / 字体对话框有效性判断 :用户点击 "取消" 时返回无效值,需通过 color.isValid()isConfirm 变量判断,避免崩溃;
  • 文件过滤器格式 :多个过滤器用 ;; 分隔,如 "文本文件 (*.txt);;图片文件 (*.jpg *.png)",不可遗漏空格。

结尾:

html 复制代码
🍓 我是草莓熊 Lotso!若这篇技术干货帮你打通了学习中的卡点:
👀 【关注】跟我一起深耕技术领域,从基础到进阶,见证每一次成长
❤️ 【点赞】让优质内容被更多人看见,让知识传递更有力量
⭐ 【收藏】把核心知识点、实战技巧存好,需要时直接查、随时用
💬 【评论】分享你的经验或疑问(比如曾踩过的技术坑?),一起交流避坑
🗳️ 【投票】用你的选择助力社区内容方向,告诉大家哪个技术点最该重点拆解
技术之路难免有困惑,但同行的人会让前进更有方向~愿我们都能在自己专注的领域里,一步步靠近心中的技术目标!

结语:本文完整覆盖了 Qt 对话框的核心知识:从模态 / 非模态 / 混合模态的区别,到 5 大内置标准对话框的实战用法,所有代码均可直接复制运行。这些内置对话框已经覆盖了绝大多数开发场景,无需重复自定义布局,能极大提升开发效率。对话框的核心是 "简洁交互"------ 避免在对话框中放置过多控件,保持功能单一,才能提升用户体验。后续可结合 QSS 美化对话框样式,或自定义对话框(继承 QDialog)实现更复杂的交互逻辑。

✨把这些内容吃透超牛的!放松下吧✨ ʕ˘ᴥ˘ʔ づきらど

相关推荐
九.九5 小时前
ops-transformer:AI 处理器上的高性能 Transformer 算子库
人工智能·深度学习·transformer
春日见5 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
恋猫de小郭5 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑
前端·人工智能·ai编程
寻寻觅觅☆5 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
YJlio5 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
deephub5 小时前
Agent Lightning:微软开源的框架无关 Agent 训练方案,LangChain/AutoGen 都能用
人工智能·microsoft·langchain·大语言模型·agent·强化学习
fpcc5 小时前
并行编程实战——CUDA编程的Parallel Task类型
c++·cuda
l1t5 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
大模型RAG和Agent技术实践5 小时前
从零构建本地AI合同审查系统:架构设计与流式交互实战(完整源代码)
人工智能·交互·智能合同审核
老邋遢6 小时前
第三章-AI知识扫盲看这一篇就够了
人工智能