##QTreeWidget 中父子节点的选中状态的相互影响和改变python版
##源代码来源于 C#、C++ 版本,经过修改后为python版本
##只要正确安装了 PyQt5 就可以正常运行
## checkState 选定状态有三种:选定=Qt.Checked、
##不选=Qt.UnChecked、半选=Qt.PartiallyChecked
##父节点 选定=Qt.Checked 则子节点全部选定=Qt.Checked,
## 包括更深层次的子节点(遍历所有子节点)
##父节点 不选=Qt.UnChecked 则子节点全部不选=Qt.UnChecked,
## 包括更深层次的子节点(遍历所有子节点)
##子节点 选定=Qt.Checked ,兄弟节点也全选定=Qt.Checked,
## 则父节点选定=Qt.Checked(一直遍历到根节点)
##子节点 选定=Qt.Checked ,兄弟节点半选=Qt.PartiallyChecked,
## 则父节点半选=Qt.PartiallyChecked(一直遍历到根节点)
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt,QSignalBlocker
#子节点更新父节点状态到根节点 父节点更新到子节点 完美
class MainWindow(QMainWindow):
def __init__(self,parent=None):
super(MainWindow,self).__init__(parent)
self.setWindowTitle("树形结构 TreeWidget 2 - by cxz")
self.treeWidget=QTreeWidget()
self.resize(400,900)
self.setCentralWidget(self.treeWidget)
self.treeWidget.header().hide()
self.treeWidget.itemChanged.connect(lambda itm:self.onTreeItemChanged(itm))
self.setStyleSheet('font-size:20px')
self.initUI()
def initUI(self):
self.treeWidget.setColumnCount(1)
root=QTreeWidgetItem(self.treeWidget)
root.setText(0,"全部")
root.setCheckState(0,Qt.Checked)
xingqi=['星期一','星期二','星期三','星期四','星期五']
wubie=['上午','下午']
sjdList=[]
for xq in xingqi:
for wb in wubie:
for n in range(1,5):
sjdList.append([xq,wb,n])
xingqiNode,wubieNode,jieciNode=None,None,None
for n in range(len(sjdList)):
if sjdList[n][0]!=sjdList[n-1][0]:
xingqiNode=QTreeWidgetItem(root)
xingqiNode.setText(0,sjdList[n][0])
xingqiNode.setData(0,Qt.UserRole,sjdList[n][0])
xingqiNode.setCheckState(0,Qt.Checked)
if sjdList[n][1]!=sjdList[n-1][1]:
wubieNode=QTreeWidgetItem(xingqiNode)
wubieNode.setText(0,sjdList[n][1])
wubieNode.setData(0,Qt.UserRole,sjdList[n][0])
wubieNode.setCheckState(0,Qt.Checked)
jieciNode=QTreeWidgetItem(wubieNode)
jieciNode.setText(0,'第'+str(sjdList[n][2])+'节')
jieciNode.setData(0,Qt.UserRole,sjdList[n][0])
jieciNode.setCheckState(0,Qt.Checked)
self.treeWidget.addTopLevelItem(root)
self.treeWidget.expandAll()
def updateChildItemCheckState(self,item):
if item is None:
return
childCount = item.childCount()
checkState = item.checkState(0)
for i in range(childCount):
childItem = item.child(i)
if childItem:
childItem.setCheckState(0, checkState)
self.updateChildItemCheckState(childItem)
def updateParentItemCheckState(self,item):
if item is None:
return
parentItem = item.parent()
if parentItem is None:
return
childCount = parentItem.childCount()
childCheckedCount = self.getChildItemCheckedCount(parentItem)
if childCount == childCheckedCount:
parentItem.setCheckState(0, Qt.Checked)
elif childCheckedCount > 0:
parentItem.setCheckState(0, Qt.PartiallyChecked)
elif childCheckedCount == 0:
parentItem.setCheckState(0, Qt.Unchecked)
self.updateParentItemCheckState(parentItem)
def getChildItemCheckedCount(self,item):
if item is None:
return 0
childCount = item.childCount()
checkedCount = 0
for n in range(childCount):
childItem = item.child(n)
if childItem:
if childItem.checkState(0) == Qt.Checked:
checkedCount += 1
return checkedCount
def onTreeItemChanged(self,item):
if item is None:
return
blocker = QSignalBlocker(self.treeWidget)#必要阻塞其他信号
self.updateChildItemCheckState(item)
self.updateParentItemCheckState(item)
if __name__=="__main__":
app=QApplication(sys.argv)
window=MainWindow()
window.show()
sys.exit(app.exec_())
##有兴趣愿意交流的朋友可以V我 cxz7558 Q我 190561115,相互学习