[ ]All1 [ ]All2
[ ]checkbox1A [ ]checkbox1B
[ ]checkbox2A [ ]checkbox2B
根据上图,需要做一些事情:
所以这更像是连锁反应设置。如果选中复选框All1,则chieckbox1A和2A将打开,并且因为它们已打开,checkbox1B和2B也打开,但复选框All2保持关闭状态。我尝试根据这个逻辑连接信号,但只有配对的逻辑100%工作。全部复选框逻辑仅在50%的时间内工作,而且不准确,并且我没有办法关闭全部复选框而不关闭所有已经选中的复选框。
真的需要帮助...... T-T
示例代码:
cbPairKeys = cbPairs.keys()
for key in cbPairKeys:
cbOne = cbPairs[key][0][0]
cbTwo = cbPairs[key][1][0]
cbOne.stateChanged.connect(self.syncCB)
cbTwo.stateChanged.connect(self.syncCB)
def syncCB(self):
pairKeys = cbPairs.keys()
for keys in pairKeys:
cbOne = cbPairs[keys][0][0]
cbOneAllCB = cbPairs[keys][0][4]
cbTwo = cbPairs[keys][1][0]
cbTwoAllCB = cbPairs[keys][1][4]
if self.sender() == cbOne:
if cbOne.isChecked() or cbTwoAllCB.isChecked():
cbTwo.setChecked(True)
else:
cbTwo.setChecked(False)
else:
if cbTwo.isChecked() or cbOneAllCB.isChecked():
cbOne.setChecked(True)
else:
cbOne.setChecked(False)
修改
感谢用户Avaris的帮助和耐心,我能够将代码简化为更清洁的代码,并且在第一和第二个期望的行为上100%工作:
#Connect checkbox pairs
cbPairKeys = cbPairs.keys()
for key in cbPairKeys:
cbOne = cbPairs[key][0][0]
cbTwo = cbPairs[key][1][0]
cbOne.toggled.connect(cbTwo.setChecked)
cbTwo.toggled.connect(cbOne.setChecked)
#Connect allCB and allRO signals
cbsKeys = allCBList.keys()
for keys in cbsKeys:
for checkbox in allCBList[keys]:
keys.toggled.connect(checkbox.setChecked)
当用户选择性地关闭模块化复选框时,仅需要关闭“全部”复选框的帮助
答案 0 :(得分:2)
如果我了解您的数据结构,我有一个解决方案。如果我错了,请纠正我:allCBList
是dict
(令人困惑的名字!:))。它的键是all*
复选框。值allCBList[key]
是list
,其复选框与all
复选框相关联。对于您的示例结构,它将是这样的:
{ All1 : [checkbox1A, checkbox1B],
All2 : [checkbox2A, checkbox2B]}
然后你需要的是:当一个复选框被切换并处于checked
状态时,如果所有其他复选框都在All*
,你需要检查checked
复选框国家。否则将取消选中。
for key, checkboxes in allCBList.iteritems():
for checkbox in checkboxes:
checkbox.toggled.connect(lambda checked, checkboxes=checkboxes, key=key: key.setChecked(checked and all(checkbox.isChecked() for checkbox in checkboxes))
我想,这句话需要一些解释:
lambda checked, checkboxes=checkboxes, key=key:
lambda
创建连接到信号的可调用对象。 toggled
传递复选框状态,并将其传递给checked
变量。 checkboxes=checkboxes
和key=key
部分将当前值传递给lambda的checkboxes
和key
参数。 (由于lambda
s)
接下来:
key.setChecked(...)
我们将checked
状态key
设置为相应的All*
复选框。在里面:
checked and all(checkbox.isChecked() for checkbox in checkboxes)
如果内部的所有内容都是all
,则{p> True
为True
,我们会检查每个checkbox
的状态。如果所有内容都为True
(即checked
返回isChecked()
),则会返回True
。
checked and ...
部分是为了使all
短路。如果当前复选框变为unchecked
,则我们无需检查其他复选框。 All*
将是unchecked
。
( PS :顺便说一下,你不需要.keys()
dict
来迭代密钥。你可以迭代{{1它将迭代dict
。)
修改:为了避免因点击任何子复选框切换keys
复选框而产生连锁反应,有必要将All*
复选框的信号更改为{{1}而不是All*
。因此,在用户互动的情况下,clicked
复选框会影响其下方的其他 。
最后,您修改的代码将是:
toggled
答案 1 :(得分:0)
您的问题是,您的复选框正在连接toggled
信号和,以便在连接的插槽中切换其状态,以便再次发出信号(因此插槽会再次执行...)而且你得到了不可预知的结果。显然这不是你想要的行为。您可以通过多种方式修复它:
clicked
信号,因为当复选框状态更改时不会重新发出您遵循哪种方法取决于您。以下代码使用第三种方法:
self.cbPair = {}
self.cbPair['0'] = (QtGui.QCheckBox('all1', parent),
QtGui.QCheckBox('all2', parent))
self.cbPair['1'] = (QtGui.QCheckBox('1a', parent),
QtGui.QCheckBox('1b', parent))
self.cbPair['2'] = (QtGui.QCheckBox('2a', parent),
QtGui.QCheckBox('2b', parent))
for v in self.cbPair.values():
for cb in v:
cb.clicked.connect(self.updateCB)
def updateCB(self):
cb = self.sender()
is_checked = cb.isChecked()
id = str(cb.text())
try:
# Update a whole column
column = int(id[-1]) - 1
rows = ('1', '2')
except ValueError:
# Update a row and the headers row
rows = (id[0], )
column = {'a': 1, 'b': 0}.get(id[-1])
if not is_checked:
for c in (0, 1):
self.cbPair['0'][c].setChecked(is_checked)
for r in rows:
self.cbPair[r][column].setChecked(is_checked)
请注意,我使用复选框文本作为UID来自行,并计算colum值。如果要为复选框使用不同的文本标签,可能需要将UID设置为每个复选框的属性。