Qt6中模态与非模态对话框区别
一.阻塞 vs 非阻塞
1.模态对话框
阻塞父窗口:打开后,用户必须先处理该对话框(关闭或完成操作),才能继续操作父窗口。
应用场景:强制用户立即响应的场景,如确认对话框、登录窗口、文件选择器等。
2.非模态对话框
不阻塞父窗口:打开后,用户可同时与对话框和父窗口交互。
应用场景:需要长时间操作的工具窗口(如调色板、属性编辑器)或提示信息(如通知气泡)。
3.核心特性对比
二.模态对话框原理与应用
1. 工作原理
事件循环阻塞:调用 exec() 启动局部事件循环
输入独占:禁用父窗口及其它窗口输入
同步返回:对话框关闭后返回 QDialog::Accepted 或 Rejected
2.代码示例
// 方式1: exec() - 阻塞模态
void MainWindow::showWindowModal()
{
ParamSettingDialog *dlg = new ParamSettingDialog(this);
dlg->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动删除;不加入这句代码会有内存泄漏
connect(dlg, &ParamSettingDialog::accepted, this, &MainWindow::applySettings);
dlg->exec(); // 阻塞模态
}
// 方式2: open() - 非阻塞但模态
void MainWindow::showWindowModal()
{
ParamSettingDialog *dlg = new ParamSettingDialog(this);
dlg->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动删除
connect(dlg, &ParamSettingDialog::accepted, this, &MainWindow::applySettings);
dlg->open(); // 非阻塞但模态
}
3.内存管理问题
// 问题代码 - 内存泄漏
void showDialog() {
auto *dlg = new ParamSettingDialog();
dlg->exec(); // 对话框关闭后指针未释放
}
// 正确方案1: 关闭时自动删除
void safeShowDialog() {
auto *dlg = new ParamSettingDialog();
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->exec(); // 对话框关闭后自动删除
}
// 正确方案2: 栈上创建
void stackSafeDialog() {
ParamSettingDialog dlg;
dlg.exec(); // 自动销毁
}
三.非模态对话框原理与应用
1.工作原理
异步显示:show() 立即返回
共享事件循环:与主窗口共享同一事件队列
并行交互:用户可同时操作主窗口和对话框
2.创建方式
// 在类声明中
class MainWindow : public QMainWindow {
Q_OBJECT
private:
ParamSettingDialog *m_paramDlg = nullptr; // 成员指针
};
// 显示非模态对话框
void MainWindow::showModelessDialog()
{
if (!m_paramDlg) {
m_paramDlg = new ParamSettingDialog(this); // 指定父对象
connect(m_paramDlg, &ParamSettingDialog::settingsChanged,
this, &MainWindow::updateSettings);
}
m_paramDlg->show(); // 显示
m_paramDlg->raise(); // 置于顶层
m_paramDlg->activateWindow(); // 激活
}
3.内存管理策略
// 方案1: 父对象自动销毁 (推荐)
m_dialog = new ParamSettingDialog(this); // 父对象析构时自动删除
// 方案2: 关闭时自动删除
m_dialog = new ParamSettingDialog();
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
// 方案3: 手动管理
void MainWindow::closeEvent(QCloseEvent *event)
{
if (m_dialog) {
m_dialog->close();
delete m_dialog;
m_dialog = nullptr;
}
QMainWindow::closeEvent(event);
}
四.内存管理黄金法则
栈优先原则:短生命周期对话框使用栈分配
父对象原则:长生命周期对话框设置父对象
自动删除标志:setAttribute(Qt::WA_DeleteOnClose)
智能指针:C++17+ 使用 std::unique_ptr 管理