关于Qt模态窗口的设置

布满荆棘的人生 2023-02-19 14:27 140阅读 0赞

QWidget 模态

模态窗口会阻止其他窗口的输入型事件(如获取焦点),但是模态窗口的子窗口不会被限制。

(设置 setAttribute(Qt::WA_showModal, true); 的方式Qt4.5已废弃,略过)

目前,Qt中设置窗口模态是通过 QWidget 的 setWindowModality() 函数:

20200621100931976.png

参数有三种枚举:

20200621100832158.png

  • Qt::NonModal :(=0)表示该窗口不是模态窗口,不会阻止其他窗口的输入。
  • Qt::WindowModal :(=1)表示该窗口是单个窗口层次结构的模态,会阻止输入到其父窗口,所有祖父母窗口以及其父窗口和祖父母窗口的所有同级窗口。(说人话就是这个模态窗口对象树上的都被阻止了,除了自己的孩子,对象树就是这个模态框得设置 parent,不然是阻塞不了别的窗口的)
  • Qt::ApplicationModal :(=2)表示该窗口是应用程序的模态窗口,会阻止本应用所有窗口的输入。

(注意,Qt::WindowModal 的窗口你得设置 parent, 不然你也阻塞不了谁啊,毕竟他只会坑爹,遇到不认识的就唯唯诺诺)

QDialog 模态

QDialog 是 QWidget 的派生类,不同于 QWidget 的默认无模态,QDialog 有三种情况:

  • 调用 show() 显示:此时的模态属性是根据你 setWindowModality 设置的模式来决定的。或者你可以设置 QDialog::setModal(bool model) ,为 false(默认 false)则表示 Qt::NonModal ,为 true 则表示 Qt::ApplicationModal 。
  • 调用 exec() 显示:此时会忽略你设置的模态属性,默认以 Qt::ApplicationModal 显示,阻塞整个应用的窗口交互,并且会同步等待返回值。
  • 调用 open() 显示:此时会忽略你设置的模态属性,默认以 Qt::WindowModal 显示,但是是异步处理,立即返回的。

相关源码赏析:

  1. int QDialog::exec()
  2. {
  3. Q_D(QDialog);
  4. if (Q_UNLIKELY(d->eventLoop)) {
  5. qWarning("QDialog::exec: Recursive call detected");
  6. return -1;
  7. }
  8. bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
  9. setAttribute(Qt::WA_DeleteOnClose, false);
  10. d->resetModalitySetByOpen();
  11. bool wasShowModal = testAttribute(Qt::WA_ShowModal);
  12. setAttribute(Qt::WA_ShowModal, true);
  13. setResult(0);
  14. show();
  15. QPointer<QDialog> guard = this;
  16. if (d->nativeDialogInUse) {
  17. d->platformHelper()->exec();
  18. } else {
  19. QEventLoop eventLoop;
  20. d->eventLoop = &eventLoop;
  21. (void) eventLoop.exec(QEventLoop::DialogExec);
  22. }
  23. if (guard.isNull())
  24. return QDialog::Rejected;
  25. d->eventLoop = nullptr;
  26. setAttribute(Qt::WA_ShowModal, wasShowModal);
  27. int res = result();
  28. if (d->nativeDialogInUse)
  29. d->helperDone(static_cast<QDialog::DialogCode>(res), d->platformHelper());
  30. if (deleteOnClose)
  31. delete this;
  32. return res;
  33. }
  34. void QDialog::open()
  35. {
  36. Q_D(QDialog);
  37. Qt::WindowModality modality = windowModality();
  38. if (modality != Qt::WindowModal) {
  39. d->resetModalityTo = modality;
  40. d->wasModalitySet = testAttribute(Qt::WA_SetWindowModality);
  41. setWindowModality(Qt::WindowModal);
  42. setAttribute(Qt::WA_SetWindowModality, false);
  43. #ifdef Q_OS_MAC
  44. setParent(parentWidget(), Qt::Sheet);
  45. #endif
  46. }
  47. setResult(0);
  48. show();
  49. }

参考

Qt 文档:https://doc.qt.io/qt-5/qt.html#WindowModality-enum

Qt 文档:https://doc.qt.io/qt-5/qdialog.html#modal-prop

发表评论

表情:
评论列表 (有 0 条评论,140人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Qt与非

    模态是指当子窗口弹出时,焦点始终被强行集中于子窗口,只要子窗口不退出,焦点就不会被释放。非模态正好相反。 从线程角度讲,模态子窗口的线程是阻塞的,父、子窗口各有一个线程,当创

    相关 Angularjs 窗口

    对话框的两种类型:模态类型和非模态类型 1 模态窗口 打开模态窗口后,只要不关闭该窗口,鼠标焦点或者光标就会一直停留在该窗口上。只有关闭该窗口后,调用窗口才能继续