PyQt5——treewidget 子选项选中互斥

这篇博客介绍了如何在PyQt5中使用QTreeWidgetItem实现树形控件的单选功能。通过重写类型并监听itemChanged信号,实现了节点前面的复选框只能选中一个的功能。同时,提供了节点展开和状态更新的逻辑代码。
摘要由CSDN通过智能技术生成
网上大部分都是treewidget按钮的选中互斥,直接setselectionmode,自己搞了个节点前面的复选框,就是打对勾的那个小框框,只能选一个。

 

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt


'''常见信号'''
# currentItemChanged: 当前条目发生更改时,发射该信号;
# itemActivated: 当条目被激活时,发射该信号;
# itemChanged: 当条目数据发生改变时,发射该信号;
# itemClicked: 点击条目时,发射该信号;
# itemCollapsed: 条目折叠时,发射该信号;
# itemDoubleClicked: 双击一个条目时,发射该信号;
# itemEntered: 当鼠标进入一个条目时,发射该信号;
# itemExpanded: 条目展开时,发射该信号;
# itemPressed: 当按下表格中的条目时,发射该信号;
# itemSelectionChanged: 选择发生更改时,将发射该信号。
class myQTreeWidgetItem(QTreeWidgetItem):       # 重写child的type
    def type(self) -> int:
        return 10
    Type = 10




class TreeWidgetDemo(QMainWindow):
    def __init__(self, parent=None,radio=True):
        self.radio=radio
        super(TreeWidgetDemo, self).__init__(parent)
        self.setWindowTitle('TreeWidget 例子')
        self.resize(500,500)


        self.attrdict={'人':['行走','静止'],'车':['1','2','3'],'障碍物':['a','b']}


        self.tree = QTreeWidget(self)
        self.tree.resize(200,200)
        self.tree.move(0,200)
        # 设置列数
        self.tree.setColumnCount(2)
        # 设置树形控件头部的标题
        self.tree.setHeaderLabels(['attr_level1', 'attr_level2'])

        # 构造treewidget
        for attr1,attr2s in self.attrdict.items():
            father=QTreeWidgetItem(self.tree)
            # father.setFlags(father.flags()|Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsAutoTristate)
            father.setText(0,attr1)
            father.setCheckState(0, Qt.Unchecked)
            for attr2 in attr2s:
                child=myQTreeWidgetItem(father)     # 重写的treewidget,child.type=10
                # child.setFlags(child.flags()|Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsAutoTristate)
                child.setText(1,attr2)
                child.setCheckState(1, Qt.Unchecked)


        self.tree.itemChanged.connect(self.itemcheckchanged)       # itemchanged  ----  checkstate 的信号self.onClicked


        # 节点全部展开
        self.tree.expandAll()


    def itemcheckchanged(self,item):
        if item.type()==10 and self.radio:      # radio控制单选与否,=true时单选,=false时可多选
            if item.checkState(1)==Qt.Checked:
                text=item.text(1)
                self.updateself(item,text)
        elif not self.radio:
            self.updateparent(item)
        elif item.type()==0:                    # 原treewidget中father.type=10
            self.updatechild()


    def updatechild(self):      # 父不选时,子全不选
        items = self.tree.findItems('', Qt.MatchContains | Qt.MatchRecursive, 0)
        for item in items:
            if  not item.parent() and item.checkState(0)==Qt.Unchecked:
                for i in range(item.childCount()):
                    item.child(i).setCheckState(1,Qt.Unchecked)

    def updateself(self,iteml,text=None): # 子选其他子不选
        parent = iteml.parent()
        if parent and self.radio:
            itemCount = parent.childCount()
            for i in range(itemCount):
                item=parent.child(i)
                if item!=iteml:
                    if item.checkState(1) == Qt.Checked:
                        item.setCheckState(1,Qt.Unchecked)
            for i in range(itemCount):
                item=parent.child(i)
                if item.text(1)==text:
                    item.setCheckState(1,Qt.Checked)
        self.updateparent(iteml)


    def updateparent(self,iteml):       # 父是否选中
        parent=iteml.parent()
        if parent is None:
            self.updatechild()
            return
        checkcount=0
        itemCount=parent.childCount()
        for i in range(itemCount):
            item=parent.child(i)
            # print(item.checkState(0))
            if item.checkState(1)==Qt.Checked:
                checkcount+=1
        if checkcount<=0:
            parent.setCheckState(0,Qt.Unchecked)
        else:
            parent.setCheckState(0,Qt.Checked)

        self.updatechild()

# 节点前面的复选框,就是打对勾的那个小框框,只能选一个
if __name__ == '__main__':
    app = QApplication(sys.argv)
    tree = TreeWidgetDemo()
    tree.show()
    sys.exit(app.exec_())

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值