Python2 PyQt4 将布尔变量连接到QCheckBox项
我遇到了一个关于QCheckBox的问题。
我想把一个布尔变量和QCheckBox连接起来,这样当我改变这个布尔变量时,QCheckBox会自动被勾选或取消勾选。
我的问题和下面的问题类似,但方向正好相反。
问题:Python3 PyQt4 创建一个简单的QCheckBox并改变一个布尔变量
我只是把那个问题中的一个解决方案复制过来了。
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class SelectionWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ILCheck = False
ILCheckbox = QCheckBox(self)
ILCheckbox.setCheckState(Qt.Unchecked)
ILCheckbox.stateChanged.connect(self.ILCheckbox_changed)
MainLayout = QGridLayout()
MainLayout.addWidget(ILCheckbox, 0, 0, 1, 1)
self.setLayout(MainLayout)
def ILCheckbox_changed(self, state):
self.ILCheck = (state == Qt.Checked)
print(self.ILCheck)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = SelectionWindow()
window.show()
window.ILCheck = True
sys.exit(app.exec_())
在这种情况下,一旦我把ILCheck设置为True,QCheckBox就会被勾选。
任何帮助都非常感谢!!!
谢谢!!!!
更新:
我在我的项目中使用MVC,这段代码只是一个示例,展示我需要的功能。布尔值ILCheck
会在其他地方使用,我不想在我的模型中调用ILCheckBox
。
我希望如果我修改ILCheck
的值,ILCheckBox
能够正确反应。
更新:
感谢大家的回复和帮助。你们的解决方案都很棒!!!我需要的方式更像是模型-视图的解决方案,这样我可以把模型部分和界面部分分开。当我想更新某些内容时,我只需要更新模型,而不需要关注界面的样子。我不能在视图类中设置这个布尔属性,所以我无法使用这个解决方案。
我不确定MVC在PyQT中是否合适。我有一个类似的解决方案,但遇到了问题。
from PyQt4 import QtGui, QtCore, uic
import sys
class CellList(QtGui.QStandardItemModel):
def __init__(self, cells = [], parent = None):
QtGui.QStandardItemModel.__init__(self, parent)
self.__cells = cells
self.add(cells)
def headerData(self, section, orientation, role):
if role == QtCore.Qt.DisplayRole:
return QtCore.QString("Cell id List")
def flags(self, index):
return QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
def add(self, cells):
for i in xrange(0, len(cells)):
item = QtGui.QStandardItem('Cell %s' % cells[i][0])
if (cells[i][1]):
item.setCheckState(QtCore.Qt.Checked)
else:
item.setCheckState(QtCore.Qt.Unchecked)
item.setCheckable(True)
self.appendRow(item)
def update(self, cells = None):
# TODO: Making this working with out clean all old Cell
self.clear()
if cells is None:
cells = self.__cells
else:
print "hi"
self.__cells = cells
print cells
self.add(cells)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
listView = QtGui.QListView()
listView.show()
data = [[85, True], (105, True), (123, False)]
model = CellList(data)
listView.setModel(model)
data[0][1] = False
model.update(data)
sys.exit(app.exec_())
这个解决方案出现了一个问题,我无法解决。我认为只有视图可以设置模型。我不确定是否可以将模型设置给单个QCheckBox
。
3 个回答
只需在调用 ILCheck 之后使用 ILCheckbox.setCheckState(Qt.Checked)
。
这里不需要信号,因为你可以直接调用一个槽函数。
如果你想多次使用这个功能,建议你写一个设置函数,这个函数可以改变 self.ILCheck
的状态,并发送一个信号。
根据你的澄清进行编辑:
- 你可以使用设置函数的方法,但不是设置 ILCheckbox 的值,而是应该调用
your_properly_named_anddefine_signal.emit()
。关于信号定义的更多信息,可以参考 http://www.pythoncentral.io/pysidepyqt-tutorial-creating-your-own-signals-and-slots/。 - 你需要将你的信号连接到一个槽,这个槽会正确地设置复选框。这个连接可以在你的控制器类的
__init__()
方法中完成。
property
是一种定义变量的方法,它在你给变量赋值或访问它时可以做一些额外的工作。下面的代码就是为了这个目的而修改的。它把 ILCheck
变成了一个属性,这样在赋值的时候也会更新复选框。关于 .setter
的错误检查没有写,但实际上通常是需要的。
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class SelectionWindow(QWidget):
def __init__(self, parent=None):
super(SelectionWindow, self).__init__(parent)
self._ILCheck = False
self.ILCheckbox = QCheckBox(self)
self.ILCheckbox.setCheckState(Qt.Unchecked)
self.ILCheckbox.stateChanged.connect(self.ILCheckbox_changed)
MainLayout = QGridLayout()
MainLayout.addWidget(self.ILCheckbox, 0, 0, 1, 1)
self.setLayout(MainLayout)
def ILCheckbox_changed(self, state):
self._ILCheck = (state == Qt.Checked)
print(self.ILCheck)
@property
def ILCheck(self):
return self._ILCheck
@ILCheck.setter
def ILCheck(self, value):
self._ILCheck = value
self.ILCheckbox.setChecked(value)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = SelectionWindow()
window.show()
window.ILCheck = True
sys.exit(app.exec_())
正如Avaris在他的回答中提到的,模拟重载操作符=
是解决这个问题的一个好方法。不过,代码还需要添加到SelectionWindow
类中。
既然我们使用的是Qt
,那么我们可以创建一个自定义的QObject
,它代表我们的“智能”布尔变量,当它的值改变时会发出信号。
class SmartBool(QObject):
valueChanged = pyqtSignal(bool) # Signal to be emitted when value changes.
def __init__(self):
super(SmartBool, self).__init__() # Call QObject contructor.
self.__value = False # False initialized by default.
@property
def value(self):
return self.__value
@value.setter
def value(self, value):
if self.__value != value:
self.valueChanged.emit(value) # If value change emit signal.
self.__value = value
现在你的代码只需要做几个小改动:
把这一行替换为:
self.ILCheck = False
改为:
self.ILCheck = SmartBool()
然后连接信号和槽,在上面那行之后的某个地方添加这一行。重要的是,你不一定要在SelectionWindow
类中进行连接
self.connect(self.ILCheck, SIGNAL("valueChanged(bool)"), ILCheckbox, SLOT("setChecked(bool)"))
为了测试结果,只需在你的“main”中添加:
window.ILCheck.value = True
下次运行示例时,你会看到复选框被选中。
完整的代码示例已添加在最后,主要是为了美观
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class SmartBool(QObject):
valueChanged = pyqtSignal(bool) # Signal to be emitted when value changes.
def __init__(self, value=False):
super(SmartBool, self).__init__() # Call QObject contructor.
self.__value = value # False initialized by default.
@property
def value(self):
return self.__value
@value.setter
def value(self, value):
if self.__value != value:
self.valueChanged.emit(value) # If value change emit signal.
self.__value = value
class SelectionWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.ILCheck = SmartBool() # Your steroides bool variable.
ILCheckbox = QCheckBox(self)
self.connect(self.ILCheck, SIGNAL("valueChanged(bool)"), ILCheckbox, SLOT("setChecked(bool)"))
ILCheckbox.setCheckState(Qt.Unchecked)
ILCheckbox.stateChanged.connect(self.ILCheckbox_changed)
MainLayout = QGridLayout()
MainLayout.addWidget(ILCheckbox, 0, 0, 1, 1)
self.setLayout(MainLayout)
def ILCheckbox_changed(self, state):
self.ILCheck = (state == Qt.Checked)
print(self.ILCheck)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = SelectionWindow()
window.show()
window.ILCheck.value = True
sys.exit(app.exec_())