在子窗口小部件活动时阻止 QMa​​inWindow ,pyqt

Posted

技术标签:

【中文标题】在子窗口小部件活动时阻止 QMa​​inWindow ,pyqt【英文标题】:Block QMainWindow while child widget is alive , pyqt 【发布时间】:2014-03-14 16:26:28 【问题描述】:

我希望当用户按下按钮时,在 MainWindow 被阻止等待表单填充后会出现一个表单

【问题讨论】:

问题标题中的“如何阻止”是什么意思? 窗体出现时主窗口无法访问 【参考方案1】:

您无需执行其他答案建议的任何操作。使用任何exec() 方法是产生错误的可靠方法,因为突然之间您的gui 代码可以重新输入。不要这样做。

您需要做的就是在显示之前设置适当的窗口模式(这是重要的部分)。所以:

widget.setWindowModality(Qt.ApplicationModal)
widget.show()

如果您希望窗口仅阻止某个其他窗口,而不是整个应用程序:

widget.setWindowFlags(widget.windowFlags() | Qt.Window)
widget.setParent(otherWindow)
widget.setWindowModality(Qt.WindowModal)
widget.show()

请注意,此代码仅适用于 PyQt4,它不适用于 Qt 5,因为窗口功能属于与 QWidget 分开的类。

【讨论】:

@Vesanto 完全相同的代码在 PyQt5 上对我有用。另外(不是给你)阅读更多关于为什么不使用exec的信息,请参阅Qt docs:doc.qt.io/qt-5/qdialog.html#exec,其中的一个示例错误是deleting the dialog's parent while the dialog is open via exec() 如何显示一个对话框只阻止一些窗口而不是整个应用程序?我试过你的代码widget.setWindowFlags(widget.windowFlags() | Qt.Window) widget.setParent(otherWindow) widget.setWindowModality(Qt.WindowModal) widget.show(),但它确实有效?【参考方案2】:

您需要使用QDialog 并使用exec 显示它,这将阻止应用程序的其余部分,直到它关闭。 exec 的返回值还告诉您表单是否在未提交更改的情况下关闭(即取消)。

这是一个简单的演示脚本,展示了如何使用QDialog

from PyQt4 import QtCore, QtGui

class Dialog(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.checkbox1 = QtGui.QCheckBox('Option one', self)
        self.checkbox2 = QtGui.QCheckBox('Option two', self)
        self.buttonOk = QtGui.QPushButton('Ok', self)
        self.buttonOk.clicked.connect(self.accept)
        self.buttonCancel = QtGui.QPushButton('Cancel', self)
        self.buttonCancel.clicked.connect(self.reject)
        layout = QtGui.QGridLayout(self)
        layout.addWidget(self.checkbox1, 0, 0, 1, 2)
        layout.addWidget(self.checkbox2, 1, 0, 1, 2)
        layout.addWidget(self.buttonOk, 2, 0)
        layout.addWidget(self.buttonCancel, 2, 1)

class Window(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        widget = QtGui.QWidget(self)
        layout = QtGui.QVBoxLayout(widget)
        self.button = QtGui.QPushButton('Show Dialog', self)
        self.button.clicked.connect(self.handleButton)
        layout.addWidget(self.button)
        self.setCentralWidget(widget)

    def handleButton(self):
        dialog = Dialog(self)
        if dialog.exec_() == QtGui.QDialog.Accepted:
            print('Option one: %s' % dialog.checkbox1.isChecked())
            print('Option two: %s' % dialog.checkbox2.isChecked())
        else:
            print('Cancelled')
        dialog.deleteLater()

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 200, 100)
    window.show()
    sys.exit(app.exec_())

【讨论】:

【参考方案3】:

这是你需要的

self.setWindowModality(QtCore.Qt.ApplicationModal)

【讨论】:

您缺少“被阻止的待处理表单填写”部分。询问的行为是对话框的 exec_() 之一。【参考方案4】:

好的,所以你想阻止父窗口,直到子窗口关闭。

dialog = QInputDialog()
dialog.exec_()

使用exec_()函数,它会一直阻塞,直到子窗口没有关闭

更多信息:

launch a PyQT window from a main PyQt window, and get the user input?

Python - make a window appear on top of another, block access to other windows until button clicked

【讨论】:

thnx,但我想放一个小部件(子窗口)而不是 QInputDialog【参考方案5】:

使用表单子类化 QDialog 或 QWidget,然后在主窗口的构造函数中像这样连接它。您需要将此代码从 c++ 转换为 python:

QObject::connect(myPushButton, SIGNAL(clicked), this, SLOT(on_myPushButton()));

//...

void MainWindow::on_myPushButton()

    Dialog d;
    int retVal = d.exec();// this is a blocking call
    // Here the user has finished filling out the form.
    // save any data that should be in the form, or respond to the retVal


编辑:添加了使用 QDialog::exec() 的文档链接

http://qt-project.org/doc/qt-5/qdialog.html#exec

希望对您有所帮助。

【讨论】:

我想放一个小部件(子窗口)而不是 QInputDialog :/ 要获得阻止功能,您应该使用QDialog。它是QWidget 的子类,几乎可以在任何方面像QWidget 一样使用。 QInputDialogQMessageBox 及其静态方法是 QDialog 的有用子类,但不是唯一的。 exec() 调用创建了一个事件循环,并让小部件的 GUI 在该循环中运行,使其保持响应。您可以在源代码中看到,它创建了一个事件循环并运行它exec() 并等待该循环。 qt.gitorious.org/qt/qt/source/…【参考方案6】:

必须创建Widget继承自Qdialog

AjoutArBase, AjoutArForm = uic.loadUiType('ajoutArticle.ui')
class AjoutArticle(AjoutArBase,QtGui.QDialog):

【讨论】:

以上是关于在子窗口小部件活动时阻止 QMa​​inWindow ,pyqt的主要内容,如果未能解决你的问题,请参考以下文章

在子创建后设置父时,子小部件对事件是透明的

当设备的(android)键盘处于活动状态时,jquery 移动弹出窗口小部件不会移动

php 将活动类添加到标记云窗口小部件中的当前标记。

在Dijit销毁小部件

当小部件具有配置活动时,无法从小部件启动活动

在子小部件中,如何在 kivy 中获取父小部件的实例