如何使 QDialog 仅针对其非模态父窗口而不是所有祖父窗口成为模态?

Posted

技术标签:

【中文标题】如何使 QDialog 仅针对其非模态父窗口而不是所有祖父窗口成为模态?【英文标题】:How to make QDialog to be modal only for its non-modal parent window, but not for the all grandparent ones? 【发布时间】:2018-03-07 14:15:38 【问题描述】:

我目前正在进行的项目需要有一个非模态对话框(我们称之为对话框“A”),它会弹出另一个对话框(我们称之为对话框“B”),这将是模态的,但仅适用于其父级(对话框“A”)。因此,当弹出对话框“B”时,它应该只阻止对话框“A”,而不应阻止 GUI 的其余部分。主窗口是对话框“A”的父窗口,而对话框“A”是对话框“B”的父窗口,这些父子关系不能更改。

有人知道如何实现这一点吗?

我试图通过依赖Qt::WindowModality 属性来实现这一点。对于对话框“A”,它设置为Qt::NonModal 值,而对于对话框“B”,它设置为Qt::WindowModal 1。通过调用 QWidget::show() 会弹出两个对话框,但是当显示对话框“B”时,它会阻塞主窗口和对话框“A”。让主窗口阻塞整个 GUI 实际上会被阻塞,这与我们的要求相冲突。

根据Qt::WindowModality 属性的Qt 文档,我们刚刚遇到的行为是意料之中的,因为那里声明Qt::WindowModal 值使其成为其父窗口和所有祖父母窗口的模式窗口。在我看来,无论父子链中的某个窗口是否是非模态窗口,为所有祖父母创建一个模态窗口的这一特性似乎都缺乏Qt::WindowModality 属性的逻辑。在显示为非模态的链中的第一个父母/祖父母之后打破这个循环是合乎逻辑的。

【问题讨论】:

您是否尝试过创建您的第一个对话框(对话框 A)而不给它一个父级?只是一个想法。不确定这是否可行。 您好 basslo,谢谢您的建议。是的,当对话框 B 弹出时,离开没有父级的对话框 A 将使 GUI 的其余部分不阻塞。这是我们作为初始解决方案已经做过的事情,但它有一个缺点,至少在我们的项目规范中是这样。这样,当 GUI 的任何部分(除了这两个对话框)被按下时,两个对话框 A 和 B 都将被发送到任务栏。根据我们的项目规范。只有通过单击某个切换按钮,这两个对话框才能在后面发送并在前面提出。 在实例化对话框时尝试使用 Qt::Dialog| Qt::WindowStaysOnTopHint 用于 Qt::WindowFlags 您好 basslo,再次感谢您的帮助。你用 Qt::Dialog 提议 | Qt::WindowsStaysOnTopHint 将完成这项工作,但它会在我们的项目中引入另一个问题。我们有很多其他与这个特定问题中提到的无关的对话。如果我们的 Dialog 设置在顶部,在这种情况下,所有其他不相关的对话框将在弹出时部分或全部被覆盖。更糟糕的是,如果它们是模态的,我们最终会处于完全无响应的 GUI 的情况,因为它们期望一些输入,但在完全覆盖时却无法获得它 【参考方案1】:

我在我的项目中遇到了这个问题,我在近一周的研究中发现的最佳解决方法是禁用父窗口:

parent.setEnable(false);

但是这个方法会影响widget和所有children[1],所以你需要在显示窗口之前启用所有children:

child.setEnabled(true); 
child.show();

主要缺点是可以关闭父窗口。但是一种解决方法是,如果您从父窗口小部件继承,您可以覆盖关闭按钮的方法,并在关闭前检查子窗口是否启用了isEnabled()

【讨论】:

以上是关于如何使 QDialog 仅针对其非模态父窗口而不是所有祖父窗口成为模态?的主要内容,如果未能解决你的问题,请参考以下文章

MFC 应用程序中的 Qt DLL - 如何使 QDialog *真正* 模态?

GUI学习之二十三——QDialog学习总结

QT开发(二十)——QT对话框

8.QT-对话框(模态与非模态)

Qt 之 模态非模态半模态窗口的介绍及 实现QDialog的exec()方法

QT Qdialog