Qt(模态对话框和非模态对话框)
Qt中的对话框分为模态和非模态两种类型,在交互方式和实现机制上有显著的区别。
模态对话框:
模态对话框会阻塞父窗口或整个应用程序的输入,必须关闭对话框之后才能继续与其他窗口交互。在Qt中,模态对话框通常通过exec()方式进行显示,该方式会创建一个事件循环,阻塞调用代码的执行,直到对话框被关闭之后,才会继续执行后面的代码。模态对话框适用于用户立即响应的场景。
阻塞性:用户必须完成对话框中的任务才能返回主窗口。
独占焦点:输入焦点被锁定在对话框内,无法切换到其他控件。
同步执行:调用代码会等待对话框关闭后才能继续执行。
自动内存管理:通常由系统管理生命周期,无需手动释放。
示例:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QDialog w;w.exec();qDebug()<<"打印";
}MainWindow::~MainWindow()
{delete ui;
}
上述这样创建一个模态窗口,因为没有进行对其进行绑定,所以没有父窗口。exec()会进行阻塞,整个应用程序事件循环都被暂停,需要对模态窗口操作完成之后,才能继续进行之后的代码。
可以看到代码被阻塞,后面的打印语句并没有执行。当关闭模态窗口,那么就会继续往下执行,就会进行打印并弹出主窗口或者与其他部分进行交互。
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QDialog* w=new QDialog(this);w->setModal(true);w->show();qDebug()<<"打印";
}MainWindow::~MainWindow()
{delete ui;
}
创建了一个窗口模态对话框,将其绑定到了一个父窗口。通过setModal()进行设置是否为模态对话框。这种方式只会阻塞所绑定的父窗口,因为通过show()进行展示,并不会阻塞整个代码的运行。只有完成当前模态对话框,才能够继续操作其父窗口和其他窗口。
setModal()函数:
setModal()
是Qt框架中QDialog类的重要成员函数,用于控制对话框的模态行为。该函数通过布尔参数设置对话框是否为模态,直接影响用户与应用程序其他部分的交互方式。
参数modal
为true时,将对话框设置为模态;为false时设置为非模态。
默认情况下,QDialog是非模态的,需显式调用setModal(true)
启用模态行为。
非模态对话框:
非模态对话框允许用户同时与对话框和其他窗口交互,不会进行阻塞,应用程序的其他部分能够执行。非模态对话框通过show()方法显示,并且通常需要在堆上分配内存,以此来延长非模态对话框的生命周期,但是需要注意的是需要绑定父窗口,可以不用手动对开辟的非模态对话框对象进行回收,因为关闭其父窗口,非模态对话框也会进行回收。如果没有进行绑定父窗口,那么必须进行手动对非模态对话框进行回收,不然会造成内存泄漏。可以设置非模态对话框设置WA_DeleteOnClose属性,确保关闭时自动释放内存。非模态对话框适合工具面板、设置窗口等辅助功能。
非阻塞性:用户可以在对话框打开后与其他窗口交互。
共享消息循环:与主窗口共享同一消息循环,不创建独立的消息泵。
异步执行:调用代码不会等待对话框关闭,可以继续执行后续操作。
手动内存管理:通常需要手动管理对话框对象的生命周期,避免内存泄漏。
示例:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QDialog* w=new QDialog(this);w->setAttribute(Qt::WA_DeleteOnClose);w->show();qDebug()<<"打印";
}MainWindow::~MainWindow()
{delete ui;
}
这样并不会阻塞父窗口,可以与父窗口或者其他部分进行交互。因为是在堆上开辟的内存,因为绑定了父窗口,Qt的对象树机制,通过父子关系管理堆对象,父对象调用析构时,会自动析构子对象。也可以setAttribute(WA_DeleteOnClose)属性避免内存泄漏。
setAttribute()函数:
setAttribute()
是Qt框架中QWidget类的重要成员函数,用于控制窗口部件的各种属性和行为。该函数通过设置不同的属性标志,可以改变窗口的显示方式、交互行为和生命周期管理。
void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on = true)
attribute
:要设置的属性,属于Qt::WidgetAttribute
枚举类型。
on
:布尔值,表示启用(true)或禁用(false)该属性,默认为true。
exec()
与show()
的区别:
exec()
启动独立事件循环,会阻塞调用线程。
show()
只是将窗口加入事件队列,立即返回。
模态对话框和非模态对话框的对比:
模态对话框:应用级模态对话框会阻塞整个应用其他窗口,窗口级模态对话框只阻塞其父窗口及其子窗口,非模态对话框不会阻塞其他窗口。
模态对话框用exec()显示,非模态对话框用show()显示。
模态对话框对象通常是栈分配,如果在堆上分配的话需要考虑释放机制,非模态对话框对象必须堆上分配并且要考虑释放机制。
模态对话框适合用于强制交互,非模态对话框适合用于可选工具。
两者主要区别在于阻塞性、实现方式和适用场景,开发时需根据具体需求选择适当类型对话框。