QT 对话框(QDialog)中 accept、reject、exec、open的使用

在 Qt 里,accept、reject、exec、open 主要都和 对话框(QDialog) 的生命周期与返回结果有关。下面按用途和区别讲清楚。


1️⃣ exec()

作用 :以模态方式 显示对话框,并阻塞当前代码执行
返回值QDialog::AcceptedQDialog::Rejected

cpp 复制代码
QDialog dlg;
int result = dlg.exec();
if (result == QDialog::Accepted) {
    // 点击了"确定"
}

特点

  • 会进入一个本地事件循环
  • 调用处会"停住",直到对话框关闭
  • 适合:设置窗口、确认窗口、必须等用户操作的场景

exec() 示例(同步、阻塞)

场景:点击按钮,必须等用户点"确定 / 取消"后再继续执行代码。

cpp 复制代码
void MainWindow::on_pushButton_clicked()
{
    QDialog dlg(this);

    if (dlg.exec() == QDialog::Accepted) {
        qDebug() << "用户点了确定";
    } else {
        qDebug() << "用户点了取消";
    }

    qDebug() << "对话框已经关闭";
}

特点

  • exec() 不返回,代码不会往下走
  • 对话框关闭后才继续执行

2️⃣ open()

作用 :以非阻塞模态 方式显示对话框
返回值:无(void)

cpp 复制代码
dlg.open();

特点

  • 不会阻塞当前代码
  • 仍然是模态(不能操作父窗口)
  • 结果通常通过 信号槽 获取
cpp 复制代码
connect(&dlg, &QDialog::accepted, this, [](){
    // 确定
});
connect(&dlg, &QDialog::rejected, this, [](){
    // 取消
});

适合

  • 不想卡住主流程
  • Qt 推荐的新写法(尤其在异步/UI 复杂场景)

open() 示例(非阻塞、推荐)

场景:打开对话框,但主逻辑不想被卡住。

cpp 复制代码
void MainWindow::on_pushButton_clicked()
{
    QDialog *dlg = new QDialog(this);

    connect(dlg, &QDialog::accepted, this, [](){
        qDebug() << "用户点了确定";
    });

    connect(dlg, &QDialog::rejected, this, [](){
        qDebug() << "用户点了取消";
    });

    dlg->open();

    qDebug() << "open() 后立刻执行这里";
}

特点

  • 不阻塞
  • 结果用信号拿
  • Qt 官方更推荐这种方式

3️⃣ accept()

作用关闭对话框,并设置结果为 Accepted

cpp 复制代码
accept();

等价于:

cpp 复制代码
done(QDialog::Accepted);

常见用途

  • "确定 / OK" 按钮
  • 表示用户确认操作成功

调用后:

  • exec() 会返回 Accepted
  • 会发出 accepted() 信号

accept() 示例("确定"按钮)

场景:点"确定"关闭对话框并返回成功。

cpp 复制代码
void MyDialog::on_okButton_clicked()
{
    // 校验通过
    accept();
}

等价于:

cpp 复制代码
done(QDialog::Accepted);

效果

  • 对话框关闭
  • exec() 返回 Accepted
  • 触发 accepted() 信号

4️⃣ reject()

作用关闭对话框,并设置结果为 Rejected

cpp 复制代码
reject();

等价于:

cpp 复制代码
done(QDialog::Rejected);

常见用途

  • "取消 / Cancel"
  • 关闭窗口
  • Esc 键

调用后:

  • exec() 会返回 Rejected
  • 会发出 rejected() 信号

reject() 示例("取消 / 关闭"按钮)

场景:用户取消操作。

cpp 复制代码
void MyDialog::on_cancelButton_clicked()
{
    reject();
}

效果

  • 对话框关闭
  • exec() 返回 Rejected
  • 触发 rejected() 信号
  • Esc 键默认也是走 reject()

5️⃣ 四者关系总结

方法 作用 是否关闭窗口 是否阻塞 结果
exec() 显示对话框 ✅ 是 返回 Accepted / Rejected
open() 显示对话框 ❌ 否 用信号获取
accept() 确认并关闭 ✅ 是 --- Accepted
reject() 取消并关闭 ✅ 是 --- Rejected

6️⃣ 实际使用建议

  • 简单同步逻辑 → 用 exec()
  • 推荐写法 / 异步 UI → 用 open() + 信号
  • 按钮回调里 → 调 accept() / reject()

完整实战示例(最常见)

自定义对话框

cpp 复制代码
class MyDialog : public QDialog
{
    Q_OBJECT
public:
    MyDialog(QWidget *parent = nullptr);
};
cpp 复制代码
MyDialog::MyDialog(QWidget *parent)
    : QDialog(parent)
{
    QPushButton *ok = new QPushButton("确定");
    QPushButton *cancel = new QPushButton("取消");

    connect(ok, &QPushButton::clicked, this, &QDialog::accept);
    connect(cancel, &QPushButton::clicked, this, &QDialog::reject);
}

调用方式 1(exec)

cpp 复制代码
MyDialog dlg(this);
if (dlg.exec() == QDialog::Accepted) {
    qDebug() << "确认操作";
}

调用方式 2(open)

cpp 复制代码
MyDialog *dlg = new MyDialog(this);
connect(dlg, &QDialog::accepted, this, [](){
    qDebug() << "确认操作";
});
dlg->open();

六、一句话记忆版

  • exec():我要等你点完
  • open():你慢慢点,我先干别的
  • accept():点了确定
  • reject():点了取消 / 关了窗口
相关推荐
牛奔1 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
寻星探路5 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
lly2024067 小时前
Bootstrap 警告框
开发语言
2601_949146537 小时前
C语言语音通知接口接入教程:如何使用C语言直接调用语音预警API
c语言·开发语言
曹牧7 小时前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
KYGALYX7 小时前
服务异步通信
开发语言·后端·微服务·ruby
zmzb01037 小时前
C++课后习题训练记录Day98
开发语言·c++
猫头虎8 小时前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven
YUJIANYUE9 小时前
PHP纹路验证码
开发语言·php
仟濹9 小时前
【Java基础】多态 | 打卡day2
java·开发语言