有没有办法 "freeze" PyQt5 中复选框的状态?
Is there a way to "freeze" the state of a checkbox in PyQt5?
我希望当我选中另一个复选框时自动选中一个复选框,并且在我取消选中另一个复选框之前不会取消选中。
我认为“冻结”是一种简单的方法,但我也对其他解决方案感兴趣。
尝试这个的示例程序是:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QCheckBox
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(500, 50, 500, 500)
self.box1 = QCheckBox('Box1', self)
self.box1.setGeometry(250, 10, 50, 50)
self.box1.stateChanged.connect(self.dothething)
self.box2 = QCheckBox('Box2', self)
self.box2.setGeometry(10, 10, 50, 50)
self.show()
def dothething(self):
if not self.box2.isChecked():
self.box2.toggle()
self.box2.freeze()
else:
self.box2.unfreeze()
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = Window()
sys.exit(app.exec_())
显然 .freeze()
和 .unfreeze()
函数不存在。
我也试过 .setCheckable
但是 CheckBox 只能冻结在未选中状态,所以这与我想要的相反。
有多种可用选项。
最明显的是禁用复选框,这是最好的选择,因为它向用户表明它不能取消选中,同时仍然显示它已选中。
classWindow(QMainWindow):
def __init__(自我):
超级().__init__()
self.setGeometry(500, 50, 500, 500)
中央= QWidget()
self.setCentralWidget(中央)
self.box1 = QCheckBox('Box1', self)
<b>self.box1.toggled.connect(self.dothething)</b>
self.box2 = QCheckBox('Box2', self)
layout = QHBoxLayout(中央)
layout.addWidget(self.box1)
layout.addWidget(self.box2)
self.show()
def dothething(自我,检查):
如果选中:
自我。box2.setChecked(真)
self.box2.setEnabled(假)
别的:
self.box2.setEnabled(真)
请注意,在上面的示例中,我使用了中央小部件并设置了布局;这是因为您应该 总是 在 QMainWindow 中使用中央小部件,还因为使用固定的几何形状有 很多 的问题和布局经理应该总是优先考虑的;在这种情况下,例如,我无法区分 box1 和 box2,因为您用于它们的几何形状导致将数字隐藏在它们的标签中。请记住,您在屏幕上看到的内容 很少 是其他人会看到的内容。
更简单的替代方法是,如果选中了另一个框,则再次选中该框;这在任何情况下都有效,无论用户使用鼠标还是键盘:
class Window(QMainWindow):
def __init__(self):
# ...
self.box2.toggled.connect(self.verifyBox2)
def verifyBox2(self, checked):
if not checked and self.box1.isChecked():
self.box2.setChecked(True)
def dothething(self, checked):
if checked:
self.box2.setChecked(True)
为了完整起见,还有其他两种可能性,但请记住,这两种可能性都依赖于 鼠标 事件,因此如果用户使用键盘导航(通过选项卡或助记符)并按下 Space 复选框仍会被切换。
第一种可能是设置WA_TransparentForMouseEvents
标志,这将忽略所有鼠标事件:
class Window(QMainWindow):
# ...
def dothething(self, checked):
if checked:
self.box2.setChecked(True)
self.box2.setAttribute(Qt.WA_TransparentForMouseEvents, True)
else:
self.box2.setAttribute(Qt.WA_TransparentForMouseEvents, False)
或者,您可以使用事件过滤器忽略左键单击事件(包括双击,因为 QCheckBox 也可以与它们切换):
class Window(QMainWindow):
def __init__(self):
# ...
self.box2.installEventFilter(self)
def eventFilter(self, source, event):
if source == self.box2:
if event.type() in (QEvent.MouseButtonPress, QEvent.MouseButtonDblClick):
return event.button() == Qt.LeftButton and self.box1.isChecked()
return super().eventFilter(source, event)
def dothething(self, checked):
if checked:
self.box2.setChecked(True)
我希望当我选中另一个复选框时自动选中一个复选框,并且在我取消选中另一个复选框之前不会取消选中。 我认为“冻结”是一种简单的方法,但我也对其他解决方案感兴趣。 尝试这个的示例程序是:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QCheckBox
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(500, 50, 500, 500)
self.box1 = QCheckBox('Box1', self)
self.box1.setGeometry(250, 10, 50, 50)
self.box1.stateChanged.connect(self.dothething)
self.box2 = QCheckBox('Box2', self)
self.box2.setGeometry(10, 10, 50, 50)
self.show()
def dothething(self):
if not self.box2.isChecked():
self.box2.toggle()
self.box2.freeze()
else:
self.box2.unfreeze()
if __name__ == '__main__':
app = QApplication(sys.argv)
ui = Window()
sys.exit(app.exec_())
显然 .freeze()
和 .unfreeze()
函数不存在。
我也试过 .setCheckable
但是 CheckBox 只能冻结在未选中状态,所以这与我想要的相反。
有多种可用选项。
最明显的是禁用复选框,这是最好的选择,因为它向用户表明它不能取消选中,同时仍然显示它已选中。
classWindow(QMainWindow):
def __init__(自我):
超级().__init__()
self.setGeometry(500, 50, 500, 500)
中央= QWidget()
self.setCentralWidget(中央)
self.box1 = QCheckBox('Box1', self)
<b>self.box1.toggled.connect(self.dothething)</b>
self.box2 = QCheckBox('Box2', self)
layout = QHBoxLayout(中央)
layout.addWidget(self.box1)
layout.addWidget(self.box2)
self.show()
def dothething(自我,检查):
如果选中:
自我。box2.setChecked(真)
self.box2.setEnabled(假)
别的:
self.box2.setEnabled(真)
请注意,在上面的示例中,我使用了中央小部件并设置了布局;这是因为您应该 总是 在 QMainWindow 中使用中央小部件,还因为使用固定的几何形状有 很多 的问题和布局经理应该总是优先考虑的;在这种情况下,例如,我无法区分 box1 和 box2,因为您用于它们的几何形状导致将数字隐藏在它们的标签中。请记住,您在屏幕上看到的内容 很少 是其他人会看到的内容。
更简单的替代方法是,如果选中了另一个框,则再次选中该框;这在任何情况下都有效,无论用户使用鼠标还是键盘:
class Window(QMainWindow):
def __init__(self):
# ...
self.box2.toggled.connect(self.verifyBox2)
def verifyBox2(self, checked):
if not checked and self.box1.isChecked():
self.box2.setChecked(True)
def dothething(self, checked):
if checked:
self.box2.setChecked(True)
为了完整起见,还有其他两种可能性,但请记住,这两种可能性都依赖于 鼠标 事件,因此如果用户使用键盘导航(通过选项卡或助记符)并按下 Space 复选框仍会被切换。
第一种可能是设置WA_TransparentForMouseEvents
标志,这将忽略所有鼠标事件:
class Window(QMainWindow):
# ...
def dothething(self, checked):
if checked:
self.box2.setChecked(True)
self.box2.setAttribute(Qt.WA_TransparentForMouseEvents, True)
else:
self.box2.setAttribute(Qt.WA_TransparentForMouseEvents, False)
或者,您可以使用事件过滤器忽略左键单击事件(包括双击,因为 QCheckBox 也可以与它们切换):
class Window(QMainWindow):
def __init__(self):
# ...
self.box2.installEventFilter(self)
def eventFilter(self, source, event):
if source == self.box2:
if event.type() in (QEvent.MouseButtonPress, QEvent.MouseButtonDblClick):
return event.button() == Qt.LeftButton and self.box1.isChecked()
return super().eventFilter(source, event)
def dothething(self, checked):
if checked:
self.box2.setChecked(True)