需求背景
自己做个查询写作素材的小系统,希望能够自由指定素材的搜索范围,于是就想到了pyqt的树形组件,但在信号槽方面,级联选择需要自己去实现。
解决方案-
treewidget有个针对所有节点的信号itemchanged,这个信号可以把发生变化的item以及列号传递过来,我的情况比较简单,每层都是单列,所以列号其实统一都是0。
-
注意接收参数需要在qtdesigner里面就写好:
-
基本的思想就是顶层节点,底层节点和中间层三种情况的分类讨论。
-
由于itemchanged是一个针对所有节点的信号,所以自然就会形成级联效果,有点像多米诺骨牌,你的动作触发了父子层的节点变化,他们的itemchanged信号也就自然被触发了。你需要考虑的就是用逻辑去覆盖不同层的情况,不需要专门为级联去写什么。
下面是我的实现方法:
def set_item_status(self, item, num):
# 如果是顶部节点,只考虑Child:
if item.childCount() and not item.parent(): #判断是顶部节点,也就是根节点
if item.checkState(num) == 0: #规定点击根节点只有两态切换,没有中间态
for i in range(item.childCount()): #遍历子节点进行状态切换
item.child(i).setCheckState(num, 0)
elif item.checkState(num) == 2:
for i in range(item.childCount()):
item.child(i).setCheckState(num, 2)
# 如果是底部节点,只考虑Parent
if item.parent() and not item.childCount():
parent_item = item.parent() #获得父节点
brother_item_num = parent_item.childCount() #获得兄弟节点的数目,包括自身在内
checked_num = 0 #设置计数器
for i in range(brother_item_num): #根据三态不同状态值进行数值累计
checked_num += parent_item.child(i).checkState(num)
if checked_num == 0: #最终结果进行比较,决定父节点的三态
parent_item.setCheckState(num, 0)
elif checked_num/2 == brother_item_num:
parent_item.setCheckState(num, 2)
else:
parent_item.setCheckState(num, 1)
# 中间层需要全面考虑
if item.parent() and item.childCount():
if item.checkState(num) == 0: #规定点击根节点只有两态切换,没有中间态
for i in range(item.childCount()): #遍历子节点进行状态切换
item.child(i).setCheckState(num, 0)
elif item.checkState(num) == 2:
for i in range(item.childCount()):
item.child(i).setCheckState(num, 2)
parent_item = item.parent() # 获得父节点
brother_item_num = parent_item.childCount() # 获得兄弟节点的数目,包括自身在内
checked_num = 0 # 设置计数器
for i in range(brother_item_num): # 根据三态不同状态值进行数值累计
checked_num += parent_item.child(i).checkState(num)
if checked_num == 0: # 最终结果进行比较,决定父节点的三态
parent_item.setCheckState(num, 0)
elif checked_num / 2 == brother_item_num:
parent_item.setCheckState(num, 2)
else:
parent_item.setCheckState(num, 1)
最终效果