要禁用对话框的按钮,您必须获得对它的引用。由于它是一个基本的 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...