问题描述
我正在尝试使用嵌套字典来实现树状结构来存储我的数据并使用 QTreeView 显示它。 对我来说,关键部分是跟踪对嵌套 dict 结构或 QTreeView 中的数据所做的更改。我尝试对 qabstractitemmodel 进行子类化,但无法弄清楚如何将 QTreeView 中所做的更改与我的嵌套 dict 结构同步,唯一有效的是在每次更改时重新填充整个树......是否可以在不重建的情况下实现这样的事情每次进行更改时都会生成一棵树?
所需的行为是这样的: 嵌套dict中的更改数据->更改会自动显示在QTreeView中。
我发现了类似的问题,但用 QTreeWidget 代替:QTreeWidget to Mirror python Dictionary
但是,这种方法也需要在每次更改时重新填充树...
嵌套字典(树数据)看起来像这样:
root_node = {
node1: { leaf1: data,leaf2: data}
node2: { node3: { leaf3: data,leaf4: data }}
}
from PyQt5.QtCore import QModelIndex,Qt,qabstractitemmodel
class TreeNode(object):
def __init__(self,data,parent=None):
self.parent_node = parent
self.node_data = data # it's also []
self.child_nodes = []
def child(self,row):
return self.child_nodes[row]
def child_count(self):
return len(self.child_nodes)
def child_number(self):
if self.parent_node is not None:
return self.parent_node.child_nodes.index(self)
return 0
def column_count(self):
return len(self.node_data)
def data(self,column):
return self.node_data[column]
def insert_children(self,position,count,columns):
if position < 0 or position > len(self.child_nodes):
return False
for row in range(count):
data = [None for v in range(columns)]
node = TreeNode(data,self)
self.child_nodes.insert(position,node)
return True
def append_child_by_node(self,node):
node.parent_node = self
self.child_nodes.append(node)
def append_child_by_data(self,data):
self.child_nodes.append(TreeNode(data,self))
def insert_columns(self,columns):
if position < 0 or position > len(self.node_data):
return False
for column in range(columns):
self.node_data.insert(position,None)
for child in self.child_nodes:
child.insert_columns(position,columns)
return True
def parent(self):
return self.parent_node
def remove_children(self,count):
if position < 0 or position + count > len(self.child_nodes):
return False
for row in range(count):
self.child_nodes.pop(position)
return True
def remove_columns(self,columns):
if position < 0 or position + columns > len(self.node_data):
return False
for column in range(columns):
self.node_data.pop(position)
for child in self.child_nodes:
child.remove_columns(position,columns)
return True
def set_data(self,column,value):
if column < 0 or column >= len(self.node_data):
return False
self.node_data[column] = value
return True
class TreeModel(qabstractitemmodel):
def __init__(self,parent=None,nested_dict=dict):
super(TreeModel,self).__init__(parent)
self.root_node = TreeNode(["Name","Type"])
self.update_tree(self.root_node,nested_dict)
print(self.root_node.child_count())
def columnCount(self,parent=QModelIndex()):
return self.root_node.column_count()
def data(self,index,role):
if not index.isValid():
return None
if role != Qt.displayRole and role != Qt.EditRole:
return None
node = self.get_node(index)
return node.data(index.column())
def flags(self,index):
if not index.isValid():
return 0
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
def get_node(self,index):
if index.isValid():
node = index.internalPointer()
if node:
return node
return self.root_node
def headerData(self,section,orientation,role=Qt.displayRole):
if orientation == Qt.Horizontal and role == Qt.displayRole:
return self.root_node.data(section)
return None
def index(self,row,parent=QModelIndex()):
if parent.isValid() and parent.column() != 0:
return QModelIndex()
parent_node = self.get_node(parent)
child_node = parent_node.child(row)
if child_node:
return self.createIndex(row,child_node)
else:
return QModelIndex()
def insertColumns(self,columns,parent=QModelIndex()):
self.beginInsertColumns(parent,position + columns - 1)
success = self.root_node.insert_columns(position,columns)
self.endInsertColumns()
return success
def insertRows(self,rows,parent=QModelIndex()):
parent_node = self.get_node(parent)
self.beginInsertRows(parent,position + rows - 1)
success = parent_node.insert_children(position,self.root_node.column_count())
self.endInsertRows()
return success
def parent(self,index):
if not index.isValid():
return QModelIndex()
child_node = self.get_node(index)
parent_node = child_node.parent()
if parent_node == self.root_node:
return QModelIndex()
return self.createIndex(parent_node.child_number(),parent_node)
def removeColumns(self,parent=QModelIndex()):
self.beginRemoveColumns(parent,position + columns - 1)
success = self.root_node.remove_columns(position,columns)
self.endRemoveColumns()
if self.root_node.column_count() == 0:
self.removeRows(0,self.rowCount())
return success
def removeRows(self,parent=QModelIndex()):
parent_node = self.get_node(parent)
self.beginRemoveRows(parent,position + rows - 1)
success = parent_node.remove_children(position,rows)
self.endRemoveRows()
return success
def rowCount(self,parent=QModelIndex()):
parent_node = self.get_node(parent)
return parent_node.child_count()
def setData(self,value,role=Qt.EditRole):
if role != Qt.EditRole:
return False
node = self.get_node(index)
result = node.set_data(index.column(),value)
if result:
self.dataChanged.emit(index,index)
return result
def setHeaderData(self,role=Qt.EditRole):
if role != Qt.EditRole or orientation != Qt.Horizontal:
return False
result = self.root_node.set_data(section,value)
if result:
self.headerDataChanged.emit(orientation,section)
return result
def update_tree(self,parent,nested_dict):
self.layoutChanged.emit()
parent.child_nodes.clear()
for k,v in nested_dict.items():
if isinstance(v,dict):
parent.append_child_by_data([k[0] if isinstance(k,tuple) else k,None])
self.update_tree(parent.child(parent.child_count() - 1),v)
else:
parent.append_child_by_data([k,None])
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)