我有一个带有取消按钮的标准QProgressDialog。如果/当用户单击取消按钮时,我不希望对话框立即隐藏,相反,我更希望禁用取消按钮并执行一些清理工作,然后在确定此工作完成后关闭QProgressDialog。如何截取当前函数?
从文档来看,我似乎应该重写:
PySide.QtGui.QProgressDialog.cancel()
重置进度对话框。PySide.QtGui.QProgressDialog.waseCanceled((变为true,直到重置进度对话框。进度对话框变得隐藏起来。
我尝试过对这个方法进行子类化,但当我单击取消按钮时,它似乎甚至没有被调用。
要禁用对话框的按钮,您必须获得对它的引用。由于它是一个基本的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...