簡體   English   中英

如何攔截QProgressDialog取消點擊

[英]How to intercept QProgressDialog cancel click

我有一個帶有取消按鈕的標准 QProgressDialog。 如果/當用戶單擊取消按鈕時,我不希望對話框立即隱藏,相反我更願意禁用取消按鈕並執行一些清理工作,然后在確定這項工作后關閉 QProgressDialog已經完成。 如何攔截當前的function?

從文檔看來我應該覆蓋:

PySide.QtGui.QProgressDialog.cancel()

重置進度對話框。 PySide.QtGui.QProgressDialog.wasCanceled() 變為真,直到進度對話框被重置。 進度對話框將隱藏。

我已經嘗試子類化此方法,但當我單擊取消按鈕時它似乎甚至沒有被調用。

要禁用對話框的按鈕,您必須獲得對它的引用。 由於它是一個基本的 QPushButton,您可以使用findChild()

dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.setEnabled(False)

考慮到從用戶體驗的角度來看,禁用一個永遠不會啟用的按鈕很煩人,所以更好的選擇是根本不顯示它, setCancelButton()解釋了如何做到這一點:

如果傳遞了nullptr ,則不會顯示取消按鈕。

在 python 術語中, nullptr表示None

dialog = QProgressDialog(self)
dialog.setCancelButton(None)

不幸的是,這不會阻止用戶通過關閉對話框或按Esc來取消對話框。

這對任何QDialog 都有效,並且為了正確避免這種情況,子類化是更好的選擇:您需要防止拒絕對話框( Esc鍵)關閉事件 雖然它們具有相似的結果,但它們的處理方式不同。

覆蓋reject() (什么都不做)會阻止任何會觸發拒絕(取消)的操作,包括按Esc

覆蓋closeEvent()需要一個額外的步驟:您必須確保事件是spontaneous() (由系統觸發 - 通常,用戶按下窗口的關閉按鈕),並最終忽略它。 這是必要的,因為您可能需要調用close()accept()以在完成該過程后實際關閉對話框。

class NonStopProgressDialog(QtWidgets.QProgressDialog):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setCancelButton(None)

    def reject(self):
        pass

    def closeEvent(self, event):
        if event.spontaneous():
            event.ignore()

請注意,沒有直接的方法可以知道自發關閉事件是由用戶(嘗試關閉窗口)還是系統(關閉時)直接觸發的。

另請注意,如果您確實需要以編程方式關閉對話框,您要么調用accept() ,要么調用基本實現,這允許您從對話框的reject()獲得正確的返回值:

    def rejectNoMatterWhat(self):
        super().reject()

最后,如果出於任何原因您仍然需要取消按鈕,則必須斷開其信號。

一般來說,這可能會完成工作:

dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.disconnect()

但是上面會斷開任何信號到任何插槽,並且在某些情況下應該避免這種情況。
我們從消息來源得知, clicked信號實際上連接到canceled()插槽,因此更好的解決方案是改為執行以下操作:

dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.clicked.disconnect(self.canceled)

由於您可能需要在父/主 class 中收到通知,因此更合適的解決方案是在上面使用的子類中創建自定義信號:

class NonStopProgressDialog(QtWidgets.QProgressDialog):
    userCancel = QtCore.pyqtSignal()
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        cancelButton = self.findChild(QPushButton)
        cancelButton.clicked.disconnect(self.canceled)
        cancelButton.clicked.connect(
            lambda: cancelButton.setEnabled(False))
        cancelButton.clicked.connect(self.userCancel)

    def reject(self):
        pass

    def closeEvent(self, event):
        if event.spontaneous():
            event.ignore()

class SomeWindow(QtWidgets.QWidget):
    def showProgress(self):
        self.progressDialog = NonStopProgressDialog(self)
        self.progressDialog.userCancel.connect(self.stopSomething)
        # ...

    def stopSomething(self):
        self.progressDialog.setCancelButtonText('Please wait')
        # do something...

暫無
暫無

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

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