python - 延迟加载子项 Qtreeview

标签 python qt pyqt pyqt4 qtreeview

我正在尝试在 TreeView 中加载子项

+top
  parent1
  parent2
  parent3

开始时,我仅使用父节点信息填充模型并将其附加到 TreeView ,树如下所示。

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 都没有任何 child 的信息。 我接下来要做的是在用户点击父节点时更新父节点(及时或延迟加载父子信息)。

所以当父节点被点击时,信号被发射

QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked(QModelIndex)'), self.update_model)

update_model 代码应该获取该父节点的子节点、更新模型、刷新树并展开父节点。

    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

当我尝试删除选定的父节点(没有子节点的那个)并尝试插入一个新的父项(有子节点)时,它最终会在没有子节点的父节点上方添加新的父节点(有子节点),所以我以重复的父节点结束

+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

只需将父节点添加到我的模型底部,因此树仍然会有重复的父节点,即

+top
  parent1
  **parent2**
  parent3
  **+parent2**
    child_a
    child_b
    child_c  

我想我正在寻找的是一种更新模型中现有节点的方法,以便可以使用其子节点更新所选(父节点)。例如

...
    self.model.UpdateExisitingNode(node_index)
...

关于如何更新模型中的节点有什么建议吗? 注意我使用的是 Windows 和 PyQt

问候

最佳答案

为了让它很好地工作,父项应该在填充子项之前显示扩展箭头。在通过任何方式(即通过鼠标、键盘以及以编程方式)扩展时填充顶级项目也很好,同时确保只在需要时发生(即仅当父级当前为空时)。

这一切都可以很简单地通过在相关项目上设置一个“可扩展”标志,然后重新实现 QStandardItemModelhasChildren 方法来实现。有了它,就可以很容易地编写方法来按需填充顶级项目。

这是一个基于您的示例代码的简单演示,它实现了所有这些:

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_())

关于python - 延迟加载子项 Qtreeview,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46778623/

相关文章:

python - django 按 Enter 并显示 ^M

python - 从具有列表元素的系列创建堆叠的 Pandas 系列

c++ - 如何处理构建目录中的文件?

python - PyQt5 的 OpenGL 模块和版本控制问题(调用不正确的 _QOpenGLFunctions_(ver))

qt - 在Qt4中,如何检查paintEvent是否由resize触发?

python - Geopandas:无法更改 geopandas 对象的 crs

c++ - Qt TableView 模型 setData() 使应用程序崩溃

qt - 使用 QSqlDatabase 使用 "cert"身份验证方法连接到 PostgreSQL 服务器

python - 移动 QSlider 到鼠标点击位置

python - Flask 和 Flask_login - 组织代码