延迟加载 child 项 Qtreeview
lazy loading child items Qtreeview
我正在尝试在树视图中加载 child 个项目
+top
parent1
parent2
parent3
开始时,我只使用 parent 节点信息填充模型并将其附加到树视图,树看起来像上面那样。
self.mytreeview=QtGui.Qtreeview()
self.model=QtGui.QStandardItemModel(self.mytreeview)
def initialise_model(self):
'''Populate the model with parent nodes only'''
#open file and process each line, each file line has the parent node info
....
for file_name_entry in fileobject:
parent_item=QtGui.QStandardItem(str(file_name_entry).strip())
parent_item.setData("this is a parent",QtCore.Qt.TooltipRole)
self.model.appendRow(parent_item)
self.mytreeview.setModel(self.model)
此时 parent 中的 none 有任何 child 信息。
我接下来要做的是更新一个parent节点,当用户点击parent节点时(及时或延迟加载一个parents child信息).
所以当 parent 节点被点击时,信号被发射
QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked(QModelIndex)'), self.update_model)
update_model 代码应该获取那个 parent 的 children,更新模型,刷新树并展开 parent节点.
def update_model(self,index):
'''Update the model by adding children to selected/clicked parent node only'''
parent_node=QtGui.QStandardItem(self.model.itemFromIndex(index))
parent_item_index=index.row()
#open the file called parent_node.txt and get all the child entries from the file...
child_index=0
for child_name_entry in parent_text_fileobject:
child_item=QtGui.QStandardItem(str(child_name_entry).strip())
child_item.setData("this is a child",QtCore.Qt.TooltipRole)
parent_item.setChild(child_index,child_item)
child_index=child_index+1
#Once all the children have been added update the model, by inserting a new row where the parent was
self.model.removeRow(parent_item_index)#remove old parent
self.model.insertRow(parent_item_index,parent_item)#insert new parent with its children
当我尝试删除选定的 parent 节点(没有 children 的节点)并尝试插入一个新的 parent 项目(有 children 的节点)它最终在没有 children 的 parent 节点上方添加了新的 parent(with children) 所以我最终得到了重复的 parent 节点
+top
parent1
parent2
+parent2
child_a
child_b
child_c
parent3
所以只是回顾一下,删除和插入即
#Once all the children have been added update the model, by inserting a new row where the parent was
self.model.removeRow(parent_item_index)#remove old parent
self.model.insertRow(parent_item_index,parent_item)#insert new parent with its children
是个坏主意。查看评论有人建议 AppendRow() 可能是答案,但我不太确定
我相信
self.model.appendRow(parent_item)#new parent with its children
只需将 parent 添加到我的模型底部,因此树仍然会有重复的 parent 节点,即
+top
parent1
**parent2**
parent3
**+parent2**
child_a
child_b
child_c
我认为我正在寻找一种更新模型中现有节点的方法,以便可以使用其 children 更新所选(parent 节点)。例如
...
self.model.UpdateExisitingNode(node_index)
...
关于如何更新模型中的节点有什么建议吗?
注意我正在使用 Windows 和 PyQt
此致
您正在复制项目,因为您正在创建另一个父项目,您应该只创建新的子项目。例如:
from PyQt4 import QtGui
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.mytreeview = QtGui.QTreeView(self)
self.setLayout(QtGui.QVBoxLayout())
self.layout().addWidget(self.mytreeview)
self.model = QtGui.QStandardItemModel(self.mytreeview)
self.mytreeview.setModel(self.model)
self.mytreeview.clicked.connect(self.update_model)
self.initialise_model()
def initialise_model(self):
for text in ["parent1", "parent2", "parent3"]:
item = QtGui.QStandardItem(text)
self.model.appendRow(item)
def update_model(self, index):
parent = self.model.itemFromIndex(index)
for text in ["children1", "children2", "children3"]:
children = QtGui.QStandardItem("{}_{}".format(parent.text(), text))
parent.appendRow(children)
self.mytreeview.expand(index)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
为了让它正常工作,父项应该在显示扩展箭头,然后它们被子项填充。在通过任何方式(即通过鼠标、键盘以及以编程方式)扩展时 填充顶级项目也很好,同时确保这仅在需要时发生(即仅当父级当前为空时)。
这一切都可以很简单地通过在相关项目上设置一个 "Expandable" 标志然后重新实现 QStandardItemModel
的 hasChildren
方法来实现。有了它,就可以很容易地编写方法来按需填充顶级项目。
这是一个基于您的示例代码的简单演示,它实现了所有这些:
import sys
from PyQt4 import QtCore, QtGui
class StandardItemModel(QtGui.QStandardItemModel):
ExpandableRole = QtCore.Qt.UserRole + 500
def hasChildren(self, index):
if self.data(index, StandardItemModel.ExpandableRole):
return True
return super(StandardItemModel, self).hasChildren(index)
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.mytreeview = QtGui.QTreeView()
self.model = StandardItemModel(self.mytreeview)
self.mytreeview.setModel(self.model)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.mytreeview)
self.mytreeview.expanded.connect(self.update_model)
self.initialise_model()
def initialise_model(self):
self.model.clear()
for file_name_entry in fileobject:
parent_item = QtGui.QStandardItem(file_name_entry.strip())
parent_item.setData(True, StandardItemModel.ExpandableRole)
parent_item.setData("this is a parent", QtCore.Qt.ToolTipRole)
self.model.appendRow(parent_item)
def update_model(self, index):
parent_item = self.model.itemFromIndex(index)
if not parent_item.rowCount():
for child_name_entry in parent_text_fileobject:
child_item = QtGui.QStandardItem(child_name_entry.strip())
child_item.setData("this is a child", QtCore.Qt.ToolTipRole)
parent_item.appendRow(child_item)
# dummy test data
fileobject = 'parent1 parent2 parent3'.split()
parent_text_fileobject = 'child_a child_b child_c'.split()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
我正在尝试在树视图中加载 child 个项目
+top
parent1
parent2
parent3
开始时,我只使用 parent 节点信息填充模型并将其附加到树视图,树看起来像上面那样。
self.mytreeview=QtGui.Qtreeview()
self.model=QtGui.QStandardItemModel(self.mytreeview)
def initialise_model(self):
'''Populate the model with parent nodes only'''
#open file and process each line, each file line has the parent node info
....
for file_name_entry in fileobject:
parent_item=QtGui.QStandardItem(str(file_name_entry).strip())
parent_item.setData("this is a parent",QtCore.Qt.TooltipRole)
self.model.appendRow(parent_item)
self.mytreeview.setModel(self.model)
此时 parent 中的 none 有任何 child 信息。 我接下来要做的是更新一个parent节点,当用户点击parent节点时(及时或延迟加载一个parents child信息).
所以当 parent 节点被点击时,信号被发射
QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked(QModelIndex)'), self.update_model)
update_model 代码应该获取那个 parent 的 children,更新模型,刷新树并展开 parent节点.
def update_model(self,index):
'''Update the model by adding children to selected/clicked parent node only'''
parent_node=QtGui.QStandardItem(self.model.itemFromIndex(index))
parent_item_index=index.row()
#open the file called parent_node.txt and get all the child entries from the file...
child_index=0
for child_name_entry in parent_text_fileobject:
child_item=QtGui.QStandardItem(str(child_name_entry).strip())
child_item.setData("this is a child",QtCore.Qt.TooltipRole)
parent_item.setChild(child_index,child_item)
child_index=child_index+1
#Once all the children have been added update the model, by inserting a new row where the parent was
self.model.removeRow(parent_item_index)#remove old parent
self.model.insertRow(parent_item_index,parent_item)#insert new parent with its children
当我尝试删除选定的 parent 节点(没有 children 的节点)并尝试插入一个新的 parent 项目(有 children 的节点)它最终在没有 children 的 parent 节点上方添加了新的 parent(with children) 所以我最终得到了重复的 parent 节点
+top
parent1
parent2
+parent2
child_a
child_b
child_c
parent3
所以只是回顾一下,删除和插入即
#Once all the children have been added update the model, by inserting a new row where the parent was
self.model.removeRow(parent_item_index)#remove old parent
self.model.insertRow(parent_item_index,parent_item)#insert new parent with its children
是个坏主意。查看评论有人建议 AppendRow() 可能是答案,但我不太确定 我相信
self.model.appendRow(parent_item)#new parent with its children
只需将 parent 添加到我的模型底部,因此树仍然会有重复的 parent 节点,即
+top
parent1
**parent2**
parent3
**+parent2**
child_a
child_b
child_c
我认为我正在寻找一种更新模型中现有节点的方法,以便可以使用其 children 更新所选(parent 节点)。例如
...
self.model.UpdateExisitingNode(node_index)
...
关于如何更新模型中的节点有什么建议吗? 注意我正在使用 Windows 和 PyQt
此致
您正在复制项目,因为您正在创建另一个父项目,您应该只创建新的子项目。例如:
from PyQt4 import QtGui
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.mytreeview = QtGui.QTreeView(self)
self.setLayout(QtGui.QVBoxLayout())
self.layout().addWidget(self.mytreeview)
self.model = QtGui.QStandardItemModel(self.mytreeview)
self.mytreeview.setModel(self.model)
self.mytreeview.clicked.connect(self.update_model)
self.initialise_model()
def initialise_model(self):
for text in ["parent1", "parent2", "parent3"]:
item = QtGui.QStandardItem(text)
self.model.appendRow(item)
def update_model(self, index):
parent = self.model.itemFromIndex(index)
for text in ["children1", "children2", "children3"]:
children = QtGui.QStandardItem("{}_{}".format(parent.text(), text))
parent.appendRow(children)
self.mytreeview.expand(index)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
为了让它正常工作,父项应该在显示扩展箭头,然后它们被子项填充。在通过任何方式(即通过鼠标、键盘以及以编程方式)扩展时 填充顶级项目也很好,同时确保这仅在需要时发生(即仅当父级当前为空时)。
这一切都可以很简单地通过在相关项目上设置一个 "Expandable" 标志然后重新实现 QStandardItemModel
的 hasChildren
方法来实现。有了它,就可以很容易地编写方法来按需填充顶级项目。
这是一个基于您的示例代码的简单演示,它实现了所有这些:
import sys
from PyQt4 import QtCore, QtGui
class StandardItemModel(QtGui.QStandardItemModel):
ExpandableRole = QtCore.Qt.UserRole + 500
def hasChildren(self, index):
if self.data(index, StandardItemModel.ExpandableRole):
return True
return super(StandardItemModel, self).hasChildren(index)
class Window(QtGui.QWidget):
def __init__(self):
super(Window, self).__init__()
self.mytreeview = QtGui.QTreeView()
self.model = StandardItemModel(self.mytreeview)
self.mytreeview.setModel(self.model)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.mytreeview)
self.mytreeview.expanded.connect(self.update_model)
self.initialise_model()
def initialise_model(self):
self.model.clear()
for file_name_entry in fileobject:
parent_item = QtGui.QStandardItem(file_name_entry.strip())
parent_item.setData(True, StandardItemModel.ExpandableRole)
parent_item.setData("this is a parent", QtCore.Qt.ToolTipRole)
self.model.appendRow(parent_item)
def update_model(self, index):
parent_item = self.model.itemFromIndex(index)
if not parent_item.rowCount():
for child_name_entry in parent_text_fileobject:
child_item = QtGui.QStandardItem(child_name_entry.strip())
child_item.setData("this is a child", QtCore.Qt.ToolTipRole)
parent_item.appendRow(child_item)
# dummy test data
fileobject = 'parent1 parent2 parent3'.split()
parent_text_fileobject = 'child_a child_b child_c'.split()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())