取消QFileDialog时如何停止关闭子窗口

时间:2019-09-27 05:29:03

标签: python pyqt pyqt5 qdialog qfiledialog

我有一个处理开放项目的父类。可以从子窗口打开项目,该子窗口调用父函数来处理打开项目。但是,当从子窗口取消文件对话框时,整个应用程序将退出。

from PyQt5.QtCore import Qt, QDateTime
from PyQt5.QtWidgets import *
from PyQt5 import QtGui

class ParentWindow(QDialog):
    def __init__(self):
        super(ParentWindow, self).__init__()
        self.cw = None

        self.setFixedSize(300, 100)
        self.button = QPushButton('Open')
        self.button.clicked.connect(self.open)

        layout = QHBoxLayout()
        layout.addWidget(self.button)
        self.setLayout(layout)

        self.show()

    def open(self):
        fileDialog = QFileDialog(self, 'Projects')
        fileDialog.setFileMode(QFileDialog.DirectoryOnly)

        if fileDialog.exec():
            self.hide()
            name = fileDialog.selectedFiles()[0]
            if self.cw:
                self.cw.close()
            self.cw = ChildWindow(self, name)

class ChildWindow(QDialog):
    def __init__(self, parent, name):
        super(ChildWindow, self).__init__(parent)
        self.setFixedSize(500, 100)
        self.setWindowTitle(name)

        self.openButton = QPushButton('Open')
        self.openButton.clicked.connect(self.parent().open)

        layout = QHBoxLayout()
        layout.addWidget(self.openButton)
        self.setLayout(layout)

        self.show()

我不知道为什么在文件对话框中按“取消”时,程序不会返回到子窗口。有没有办法让父母负责打开项目并解决此问题?

2 个答案:

答案 0 :(得分:1)

问题可能出在hideshow事件的不同事件发生时间上:我猜想,直到open函数返回之前,Qt尚未“注册”子项作为将检查QApplication.quitOnLastWindowClosed()选项的窗口,这意味着即使子窗口显示了一段时间,它仍然“认为”只有一个窗口(父窗口)。

根据您的要求,有两种可能性:

  • 在应用程序实例上使用setQuitOnLastWindowClosed(False),记得在父窗口(或您要在关闭时退出的任何其他窗口)的CloseEvent中调用quit
  • 使用QTimer.singleShot(1, self.hide)应该延迟隐藏时间,以免出现此问题;

第一种解决方案通常更好,我强烈建议您使用它。
我什至不确定使用一毫秒的延迟实际上是否足以允许向应用程序发送“存在新窗口”通知:可能需要更大的数量,并且该值也可以是任意值,具体取决于各种条件(包括平台实施)。
根据{{​​3}},关闭顶级窗口小部件后,它会立即检查所有QApplication.topLevelWidgets(),但是根据我的测试,列表没有立即更新:ChildWindow通常“出现” 一些show()之后的时间,但有时(通常在<2 ms之后)根本没有出现在列表中。

答案 1 :(得分:1)

这是一个非常简单的解决方法:

def open(self):
    fileDialog = QFileDialog(self, 'Projects')
    fileDialog.setAttribute(Qt.WA_QuitOnClose, False)

或更简单:

def open(self):
    fileDialog = QFileDialog(self.sender(), 'Projects')

这里的问题是,每当关闭一个窗口时,Qt都会检查是否还应关闭其他任何窗口。在大多数情况下,如果满足以下两个条件,它将自动关闭窗口:

  1. 设置了WA_QuitOnClose属性,
  2. 没有父母,父母被隐藏

不幸的是,在您的示例中,对于文件对话框和子窗口都是如此,这将导致两个窗口都关闭。另外,由于quitOnLastWindowClosed在默认情况下为true,因此该应用程序还将自动退出。

上面的第一个修复程序通过确保至少一个窗口没有设置quit-on-close属性来工作,第二个修复程序通过确保文件对话框的父代始终是可见窗口来工作。