QDialog 模态对话框与事件循环(exec其实就是调用了show和eventLoop.exec)

摘要:
当然,你喜欢用heap,也没问题:Dialog*dlg=newQDialog();dlg-˃exec();deletedlg;模态对话框前面的show()与exec()并不是模态与非模态的区别。看QDialog源代码吧intQDialog::exec(){Q_D;...setAttribute;...show();...QEventLoopeventLoop;eventLoop.exec;...}看到答案没:exec()先设置modal属性,而后调用show()显示对话框,最后启用事件循环事件循环Qt程序时事件驱动的,每个程序,我们需要调用QApplication::exec()来启用事件循环。对与QDialog来说,当它自己的QEventLoop启用时,主程序的QEventLoop当然是处于暂停状态了。

起源

qtcn中文论坛中有网友问到:

假设程序正常运行时,只有一个简单的窗体A,此时只有一个GUI主线程,在这个主线程中有一个事件循环处理窗体上的事件。当此程序运行到某阶段时,弹出一个模态窗体B(书上说模态窗体是有其自己的事件循环的),此时模态窗体B是否会有一个对应的子线程处理其事件循环?

这儿其实有两个问题:

  • 模态对话框 和 事件循环 没有必然联系
  • 事件循环 和 子线程 没有必然联系

题外:

如果进一步呢?其实我们还可以说:

  • 模态对话框 和 QDialog 没必要联系

QDialog 对话框

两种常规用法:

非模态

QDialog * dlg = new QDialog()
dlg->show();

当然,这儿用指针(即分配到heap中)不是必须的。(有疑问?或者有时发现窗口一闪而过?那么你需要了解C、C++中变量的作用域和生存周期)

模态

QDialog dlg;
dlg.exec();

这种情况下,我们一般都是将对象分配上 stack 上,而不是heap上。

当然,你喜欢用 heap,也没问题:

Dialog * dlg = new QDialog();
dlg->exec();
delete dlg;

模态对话框

前面的 show() 与 exec() 并不是模态与非模态的区别。

想让一个Widget成为模态,我们只需要对其设置:

setAttribute(Qt::WA_ShowModal, true);

注意:这是QWidget的成员函数,也就是说,QWidget可以显示为模态或非模态!

setWindowModality

除了直接调用setAttribute外,QWidget 提供了一个易用的函数,来设置窗体的模态。其源码如下:

void QWidget::setWindowModality(Qt::WindowModality windowModality)
{
    data->window_modality = windowModality;
    // setModal_sys() will be called by setAttribute()
    setAttribute(Qt::WA_ShowModal, (data->window_modality != Qt::NonModal));
    setAttribute(Qt::WA_SetWindowModality, true);
}

注意:该函数的参数取值:NonModal、WindowModal、ApplicationModal 分别对应默认情况下的

  • QDialog::show()
  • QDialog::open()
  • QDialog::exec()

如果你没有使用QDialog::open()的需求,你可能也不需要该函数。

setModal

除了QWidget提供的成员,QDialog 提供了 setModal 的成员函数,我们看看其代码:

void QDialog::setModal(bool modal)
{
    setAttribute(Qt::WA_ShowModal, modal);
}

不用解释了吧?我们要显示模态对话框,只需要类似下面的代码:

QDialog * dlg = new QDialog();
dlg->setAttribute(Qt::WA_ShowModal, true);
dlg->show();

exec()

有问题是不?为啥exec() 直接可以显示模态对话框呢?看QDialog源代码吧

int QDialog::exec()
{
    Q_D(QDialog);
...
    setAttribute(Qt::WA_ShowModal, true);
...
    show();
...
    QEventLoop eventLoop;
    (void) eventLoop.exec(QEventLoop::DialogExec);
...
}

看到答案没:exec() 先设置modal属性,而后调用 show() 显示对话框,最后启用事件循环

事件循环

Qt 程序时事件驱动的,每个程序,我们需要调用 QApplication::exec() 来启用事件循环。

int QCoreApplication::exec()
{
...
    QEventLoop eventLoop;
    int returnCode = eventLoop.exec();
...
    return returnCode;
}

用前面的 QDialog::exec() 一样,都是调用的 QEventLoop::exec()

int QEventLoop::exec(ProcessEventsFlags flags)
{
    Q_D(QEventLoop);
...
    while (!d->exit)
        processEvents(flags | WaitForMoreEvents | EventLoopExec);
...
    return d->returnCode;
}

bool QEventLoop::processEvents(ProcessEventsFlags flags)
{
    Q_D(QEventLoop);
    if (!d->threadData->eventDispatcher)
        return false;
    if (flags & DeferredDeletion)
        QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
    return d->threadData->eventDispatcher->processEvents(flags);
}

进一步:这将调用平台相关的函数,比如在windows下

bool QGuiEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
    if (!QEventDispatcherWin32::processEvents(flags))
        return false;
    if (configRequests)                        // any pending configs?
        qWinProcessConfigRequests();
    return true;
}

事件循环和线程没有必然的联系,事件循环可以用在QThread中,而且从Qt4.4开始,QThread的run函数默认就调用了自己的事件循环。

对与QDialog来说,当它自己的QEventLoop启用时,主程序的 QEventLoop 当然是处于暂停状态了。说到底,就是两个死循环,一个在内,一个在外,只有里面的退出后,外边的循环才会执行。不过由于两个循环执行的命令是基本一样的,都是调用并处理程序收到的各种事件,所以,可能变得不容易理解

http://blog.csdn.net/dbzhang800/article/details/6300416

免责声明:文章转载自《QDialog 模态对话框与事件循环(exec其实就是调用了show和eventLoop.exec)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇CRC32JAVA获取客户端请求的当前网络ip地址(附:Nginx反向代理后获取客户端请求的真实IP)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MFC中CWnd类及其派生类对话框、消息处理、窗口操作

http://hi.baidu.com/xiaorida21/blog/item/8d8eb77a22eedee52e73b39e.html CWnd类 我们在屏幕上看到的所有对象都和窗口有关,它们或者派生于CWnd,属继承关系,如对话框、工具栏、状态栏、子控件;或者被CWnd合成,属服务员与服务对象关系,如图标、菜单、显示设备。 CWnd类封装的窗口操...

app中的弹窗—(对话框,动作菜单,浮出层,toast,snackbar等)

再也不要“滥用”弹窗啦 转至:https://www.zcool.com.cn/article/ZODAxNDc2.html 一.前言 我们口中常说的弹窗其实是个广义的范围,包括了对话框,动作菜单,浮出层,toast,snackbar等,这么多类型的弹窗在使用中很容易混乱或者说滥用,反而得不偿失,给用户带来更多困扰,故本篇文章主要分析和总结不同弹窗的使用...

非模态对话框居中显示

第一种最简单,就是在建立对话框模板的时候,在MoreStyle中选择Center。这样对话框就会居中了。 第二种方式是使用CenterWindow();,如pDlg->CenterWindow,调用了这个函数以后再调用显示函数。 第三种方式,就是计算父窗口的坐标,然后使用MoveWindow或者是SetWindowPos函数来使窗口移到我们想要的位置...

cocos2d-x 模态对话框的实现

心情不好,恩,不扯淡了。直接讲。 ================================== 在泰然看了一篇实现模态对话框的文章,写的还不错,然后在其基础上加了我简单加了一层灰色透明背景。这样子界面效果看起来会更友好一点,好吧。原谅我的无耻,原创转载什么的也不在意了,原文在这里,今天感觉有点累,恩。主要是大神不能带我飞了,非常是失落,好吧...

bootstrap添加多个模态对话框支持

  因为项目需要,在页面交互上要弹出多个dialog窗口,而bootstrap的modal支持弹出dialog窗口,但是在此基础上,会出先遮罩层越来越多,背景越来越黑的情况代码具体如下:(function(){ modal = {}; modal.openDialog = function(url, title, width, height, id){...

【转】VC 模式对话框和非模式对话框的创建,销毁和区别

原文网址:http://blog.csdn.net/mycaibo/article/details/6002151 VC 模式对话框和非模式对话框的创建,销毁和区别  在WIN32中,模式对话框的创建一般是使用DialogBox来进行创建的。而非模式对话框则是利用CreateWindow来创建的。在MFC或是WTL中,模式对话框一般是使用DoModal,...