0

我有一个带有取消按钮的标准 QProgressDialog。如果/当用户单击取消按钮时,我不希望对话框立即隐藏,而是我更愿意禁用取消按钮并执行一些清理工作,然后在我确定此工作后关闭 QProgressDialog完成了。如何拦截当前功能?

从文档看来我应该覆盖:

PySide.QtGui.QProgressDialog.cancel()

重置进度对话框。PySide.QtGui.QProgressDialog.wasCanceled() 变为真,直到进度对话框被重置。进度对话框变为隐藏。

我已经尝试对这个方法进行子类化,但是当我单击取消按钮时,它似乎甚至没有被调用。

4

1 回答 1

1

要禁用对话框的按钮,您必须获得对它的引用。由于它是一个基本的 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 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...
于 2022-02-23T00:48:29.467 回答