如何拦截QProgressDialog取消点击
How to intercept QProgressDialog cancel click
我有一个带有取消按钮的标准 QProgressDialog。 If/When 用户点击取消按钮,我不希望对话框立即隐藏,相反我宁愿禁用取消按钮并执行一些清理工作,然后在确定后关闭 QProgressDialog这项工作已经完成。
如何拦截当前函数?
从文档看来我应该覆盖:
PySide.QtGui.QProgressDialog.cancel()
Resets the progress dialog. PySide.QtGui.QProgressDialog.wasCanceled()
becomes true until the progress dialog is reset. The progress dialog
becomes hidden.
我试过将此方法子类化,但当我单击取消按钮时它似乎甚至没有被调用。
要禁用对话框的按钮,您必须获得对它的引用。由于它是一个基本的QPushButton,你可以使用findChild()
:
dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.setEnabled(False)
考虑到禁用一个 永远不会 启用的按钮从用户体验的角度来看很烦人,因此更好的选择是 not 展示它,setCancelButton()
解释如何做:
If nullptr
is passed, no cancel button will be shown.
在python术语中,nullptr
表示None
:
dialog = QProgressDialog(self)
dialog.setCancelButton(None)
遗憾的是,这不会阻止用户通过关闭对话框或按 Esc.
来取消对话框
这对 any QDialog 有效,并且,为了正确避免这种情况,subclassing 是更好的选择:你需要防止 拒绝对话框(Esc键)和关闭事件。虽然它们的结果相似,但处理方式不同。
覆盖 reject()
(什么都不做)会阻止任何会触发拒绝(取消)的操作,包括按 Esc.
覆盖 closeEvent()
需要一个额外的步骤:您必须确保事件是 spontaneous()
(由系统触发 - 通常,用户按下 [=95= 的关闭按钮]),并最终忽略它。这是必要的,因为您可能需要调用 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()
请注意,没有直接的方法可以知道 自发的 关闭事件是由用户直接触发的(试图关闭 window),还是系统(关机时)。
另请注意,如果您 需要以编程方式关闭对话框,您要么调用 accept()
,要么调用基础实现,这样您就可以获取来自对话框 reject()
:
的正确 return 值
def rejectNoMatterWhat(self):
super().reject()
最后,如果出于任何原因您仍然需要取消按钮,则必须断开其信号。
一般来说,这可能会起作用:
dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.disconnect()
但是上面会断开 any 信号到 any 插槽,在某些情况下应该避免这种情况。
我们从 the sources 得知 clicked
信号实际上连接到 canceled()
插槽,因此更好的解决方案是改为执行以下操作:
dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.clicked.disconnect(self.canceled)
由于您可能需要在 parent/main class 中收到通知,更合适的解决方案是在上面使用的子 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...
我有一个带有取消按钮的标准 QProgressDialog。 If/When 用户点击取消按钮,我不希望对话框立即隐藏,相反我宁愿禁用取消按钮并执行一些清理工作,然后在确定后关闭 QProgressDialog这项工作已经完成。 如何拦截当前函数?
从文档看来我应该覆盖:
PySide.QtGui.QProgressDialog.cancel()
Resets the progress dialog. PySide.QtGui.QProgressDialog.wasCanceled() becomes true until the progress dialog is reset. The progress dialog becomes hidden.
我试过将此方法子类化,但当我单击取消按钮时它似乎甚至没有被调用。
要禁用对话框的按钮,您必须获得对它的引用。由于它是一个基本的QPushButton,你可以使用findChild()
:
dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.setEnabled(False)
考虑到禁用一个 永远不会 启用的按钮从用户体验的角度来看很烦人,因此更好的选择是 not 展示它,setCancelButton()
解释如何做:
If
nullptr
is passed, no cancel button will be shown.
在python术语中,nullptr
表示None
:
dialog = QProgressDialog(self)
dialog.setCancelButton(None)
遗憾的是,这不会阻止用户通过关闭对话框或按 Esc.
来取消对话框这对 any QDialog 有效,并且,为了正确避免这种情况,subclassing 是更好的选择:你需要防止 拒绝对话框(Esc键)和关闭事件。虽然它们的结果相似,但处理方式不同。
覆盖 reject()
(什么都不做)会阻止任何会触发拒绝(取消)的操作,包括按 Esc.
覆盖 closeEvent()
需要一个额外的步骤:您必须确保事件是 spontaneous()
(由系统触发 - 通常,用户按下 [=95= 的关闭按钮]),并最终忽略它。这是必要的,因为您可能需要调用 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()
请注意,没有直接的方法可以知道 自发的 关闭事件是由用户直接触发的(试图关闭 window),还是系统(关机时)。
另请注意,如果您 需要以编程方式关闭对话框,您要么调用 accept()
,要么调用基础实现,这样您就可以获取来自对话框 reject()
:
def rejectNoMatterWhat(self):
super().reject()
最后,如果出于任何原因您仍然需要取消按钮,则必须断开其信号。
一般来说,这可能会起作用:
dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.disconnect()
但是上面会断开 any 信号到 any 插槽,在某些情况下应该避免这种情况。
我们从 the sources 得知 clicked
信号实际上连接到 canceled()
插槽,因此更好的解决方案是改为执行以下操作:
dialog = QProgressDialog(self)
cancelButton = dialog.findChild(QPushButton)
cancelButton.clicked.disconnect(self.canceled)
由于您可能需要在 parent/main class 中收到通知,更合适的解决方案是在上面使用的子 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...