Qt的事件循环和QDialog有没有联系

suoniao 2021-03-24
需要:0索币

假设程序正常运行时,只有一个简单的窗体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 当然是处于暂停状态了。说到底,就是两个死循环,一个在内,一个在外,只有里面的退出后,外边的循环才会执行。不过由于两个循环执行的命令是基本一样的,都是调用并处理程序收到的各种事件,所以,可能变得不容易理解

————————————————

原文链接:https://blog.csdn.net/dbzhang800/article/details/6300416

回帖
  • 消灭零回复
相关主题
QListWidget滚动的时候显示不完整 滚动条模式导致的哦 0
Qt设置顶层面板背景透明Qt::WA_TranslucentBackground 隐藏边框Qt::FramelessWindowHint 0
QCheckBox的QSS样式表总结 0
Qt通过qRegisterMetaType注册自定义数据类型 0
QListwidget触发2次itemClicked事件 0
Qt利用QLabel组件来显示图片 0
TableView自定义代理QStyledItemDelegate实现ComboBox 0
Qt利用QGraphicsView类实现图片放大缩小平移显示 0
Qt实现非阻塞延迟方法sleep 0
Qt实现webdav客户端功能支持https协议的webdav客户端 0
Qt操作windows注册表的方法 bat从注册表中将键值删除 0
重写QSqlQueryModel实现QTableView显示图片 0
QLocalServer基于本地套接字socket的服务端server 0
Qt使用动态库的方法 QLibrary库的典型用法 0
QT实现视频播放器界面开发 0
QTableview实现鼠标放上面显示不同颜色 0
Qt的QTableView自定义委托详解 0
QTableView利用自定义委托实现日期显示下拉菜单文字颜色等 0
Qt利用QApplication::sendEvent和QMouseEvent模拟鼠标点击事件 0
Qt获取父进程路径和父进程ID代码 0
相关主题
QListWidget滚动的时候显示不完整 滚动条模式导致的哦 0
Qt设置顶层面板背景透明Qt::WA_TranslucentBackground 隐藏边框Qt::FramelessWindowHint 0
QMenu和QMenuBar样式表大全 qss 0
QT定时器startTimer和timerEvent事件 每隔interval 毫秒就会启动一次 0
C语言内存分配函数malloc和calloc的区别 0
QCheckBox的QSS样式表总结 0
Qt通过qRegisterMetaType注册自定义数据类型 0
QListwidget触发2次itemClicked事件 0
打印机USB驱动开发之实现打印服务器 0
Qt利用QLabel组件来显示图片 0
TableView自定义代理QStyledItemDelegate实现ComboBox 0
Qt利用QGraphicsView类实现图片放大缩小平移显示 0
Qt实现非阻塞延迟方法sleep 0
海康相机SDK的C++对应的接口 0
Qt实现webdav客户端功能支持https协议的webdav客户端 0
CHKDSK解决 移动硬盘只能看见盘符其它信息都看不见另外双击也打不开 0
gogs一直报errror:dial tcp xxx.xxx.xxx.xxx 宿主机的ip 0
索鸟快传2.1.2发布 0
索鸟快传2.1.1发布 0
Qt操作windows注册表的方法 bat从注册表中将键值删除 0