簡體   English   中英

取消 QFileDialog 時如何停止子 window 關閉

[英]How to stop child window closing when a QFileDialog is cancelled

我有一個處理開放項目的父 class。 可以從調用父 function 來處理打開項目的子 window 打開項目。 但是,當從子 window 取消文件對話框時,整個應用程序將退出。

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()

我無法弄清楚為什么在文件撥號中按下取消時程序不會返回子 window。 有沒有辦法讓父母負責打開項目並解決這個問題?

The problem probably resides on the different event timings of both hide and show events: I suppose that, until the open function returns, Qt has not yet "registered" the child as a window that will check against the QApplication.quitOnLastWindowClosed() option,這意味着即使子 window 顯示了一小部分時間,它仍然“認為”只有一個 window(父)。

根據您的要求,有兩種可能:

  • 在應用程序實例上使用setQuitOnLastWindowClosed(False) ,記住在父 window(或任何其他您想要在關閉時退出的 window)的 CloseEvent 中調用quit
  • 使用QTimer.singleShot(1, self.hide) ,它應該足夠延遲隱藏以避免這個問題;

第一個解決方案通常更好,我強烈建議您使用它。
我什至不確定使用一毫秒的延遲實際上是否足以允許向應用程序發出“新的 window 存在”通知:可能需要更高的數量,並且該值也可能是任意的,具體取決於各種條件(包括平台實現)。
根據源代碼,一旦頂級小部件關閉,它就會檢查所有QApplication.topLevelWidgets() ,但根據我的測試,該列表不會立即更新: ChildWindow 通常在show()一段時間后“出現”,但有時(通常 <2 ms 之后)它根本不會出現在列表中。

這是一個非常簡單的修復:

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

甚至更簡單:

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

這里的問題是,每當關閉 window 時,Qt 就會檢查是否還有其他 windows 也應該關閉。 在大多數情況下,如果滿足這兩個條件,它會自動關閉一個 window:

  1. WA_QuitOnClose屬性已設置,並且
  2. 沒有父級,或者父級被隱藏

不幸的是,在您的示例中,文件對話框和子 window 都是如此,這導致 windows 都被關閉。 另外,由於quitOnLastWindowClosed默認為true,應用程序也會自動退出。

上面的第一個修復通過確保至少一個 window 沒有設置關閉時退出屬性來工作,第二個通過確保文件對話框的父級始終是可見的 window 來工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM