Dictionary Python的Qt:Qtreeview(来自字典)

Dictionary Python的Qt:Qtreeview(来自字典),dictionary,parent,children,qabstractitemmodel,Dictionary,Parent,Children,Qabstractitemmodel,以下使用Qt的“简单树模型示例”作为基础,从给定的字典构建大部分QTreeView #!/usr/bin/env python # -*- coding: utf-8 -*- import sys from PySide2.QtWidgets import QApplication, QWidget, QGroupBox, QHBoxLayout, QVBoxLayout, QTreeView from PySide2.QtCore import Qt, QAbstractItemModel,

以下使用Qt的“简单树模型示例”作为基础,从给定的字典构建大部分QTreeView

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
from PySide2.QtWidgets import QApplication, QWidget, QGroupBox, QHBoxLayout, QVBoxLayout, QTreeView
from PySide2.QtCore import Qt, QAbstractItemModel, QModelIndex


class GUIWindow(QWidget):
    def __init__(self, parent=None):
        super(GUIWindow, self).__init__(parent)
        """ Setup UI """

        self.setWindowTitle("QTreeView from Dictionary")

        groupbox_model = QGroupBox('TreeView')  # Create a Group Box for the Model

        hbox_model = QHBoxLayout()  # Create a Horizontal layout for the Model
        vbox = QVBoxLayout()  # Create a Vertical layout for the Model Horizontal layout

        tree_view = QTreeView()    # Instantiate the View

        headers = ["Dictionary"]

        tree = {'Root': {"Level_1": {"Item_1": 1.10, "Item_2": 1.20, "Item_3": 1.30},
                         "Level_2": {"SubLevel_1":
                                         {"SubLevel_1_item1": 2.11, "SubLevel_1_Item2": 2.12, "SubLevel_1_Item3": 2.13},
                                     "SubLevel_2":
                                         {"SubLevel_2_Item1": 2.21, "SubLevel_2_Item2": 2.22, "SubLevel_2_Item3": 2.23}},
                         "Level_3": {"Item_1": 3.10, "Item_2": 3.20, "Item_3": 3.30}}}

        # Set the models
        model = TreeModel(headers, tree)
        tree_view.setModel(model)

        hbox_model.addWidget(tree_view)     # Add the Widget to the Model Horizontal layout
        groupbox_model.setLayout(hbox_model)    # Add the hbox_model to layout of group box
        vbox.addWidget(groupbox_model)    # Add groupbox elements to vbox
        self.setLayout(vbox)


class TreeModel(QAbstractItemModel):
    def __init__(self, header, data, parent=None):
        super(TreeModel, self).__init__(parent)
        """ subclassing the standard interface item models must use and 
        implementing index(), parent(), rowCount(), columnCount(), and data()."""

        rootData = header
        self.rootItem = TreeNode(rootData)
        level = 0
        self.createData(data, level)

    def createData(self, data, level):
        parents = [self.rootItem]
        sublevel = 2

        if type(data) == dict:
            level += 1
            for key, values in data.items():
                if level > sublevel:
                    parents.append(parents[-1].child(parents[-1].childCount() - 1))
                if level > sublevel + 1:
                    sublevel += 1
                    if level > sublevel:
                        parents.append(parents[-1].child(parents[-1].childCount() - 1))
                # Append a new item to the current parent's list of children
                parent_item = parents[-1]
                parent_item.insertChildren(parent_item.childCount())
                parent_item.child(parent_item.childCount() - 1).setData([key])

                self.createData(values, level)    # Recursion to iterate through nested dict
                sublevel += 1

    def index(self, row, column, index=QModelIndex()):
        """ Returns the index of the item in the model specified by the given row, column and parent index """

        if not self.hasIndex(row, column, index):
            return QModelIndex()
        if not index.isValid():
            item = self.rootItem
        else:
            item = index.internalPointer()

        child = item.child(row)
        if child:
            return self.createIndex(row, column, child)
        return QModelIndex()

    def parent(self, index):
        """ Returns the parent of the model item with the given index
        If the item has no parent, an invalid QModelIndex is returned """

        if not index.isValid():
            return QModelIndex()
        item = index.internalPointer()
        if not item:
            return QModelIndex()

        parent = item.parentItem
        if parent == self.rootItem:
            return QModelIndex()
        else:
            return self.createIndex(parent.childNumber(), 0, parent)

    def rowCount(self, index=QModelIndex()):
        """ Returns the number of rows under the given parent
        When the parent is valid it means that rowCount is returning the number of children of parent """

        parent = self.getItem(index)
        return parent.childCount()

    def columnCount(self, index=QModelIndex()):
        """ Returns the number of columns for the children of the given parent """

        if index.isValid():
            return index.internalPointer().columnCount()
        else:
            return self.rootItem.columnCount()

    def data(self, index, role=Qt.DisplayRole):
        """ Returns the data stored under the given role for the item referred to by the index """

        if index.isValid() and role == Qt.DisplayRole:
            return index.internalPointer().data(index.column())
        elif not index.isValid():
            return self.rootItem.getData()

    def getItem(self, index):
        """ Retrieves the tree node with a given index """

        if index.isValid():
            item = index.internalPointer()
            if item:
                return item
        return self.rootItem

    def headerData(self, section, orientation, role):
        """ Returns the data for the given role and section in the header with the specified orientation """

        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return self.rootItem.data(section)


class TreeNode(object):
    def __init__(self, data, parent=None):

        self.parentItem = parent
        self.itemData = data
        self.children = []

    def child(self, row):
        return self.children[row]

    def childCount(self):
        return len(self.children)

    def childNumber(self):
        if self.parentItem:
            return self.parentItem.children.index(self)
        return 0

    def columnCount(self):
        return 1

    def data(self, column):
        return self.itemData[column]

    def insertChildren(self, position):
        item = TreeNode([1], self)
        self.children.insert(position, item)
        return True

    def parent(self):
        return self.parentItem

    def setData(self, value):
        self.itemData[0] = value
        return True


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle("plastique")  # ("cleanlooks")
    form = GUIWindow()
    form.show()
    sys.exit(app.exec_())
以上是一个好方法吗

以及需要哪些代码(必需/更改)来:

  • 将“根”作为顶层

  • 是否将键“Item_1”的“值”显示为“Item_1”的子项,例如1.10


  • 感谢您的建议。

    已解决-如果有兴趣,下面显示了解决这两个问题的完整代码

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import sys
    from PySide2.QtWidgets import QApplication, QWidget, QGroupBox, QHBoxLayout, QVBoxLayout, QTreeView
    from PySide2.QtCore import Qt, QAbstractItemModel, QModelIndex
    
    
    class GUIWindow(QWidget):
        def __init__(self, parent=None):
            super(GUIWindow, self).__init__(parent)
            """ Setup UI """
    
            self.setWindowTitle("QTreeView from Dictionary")
    
            groupbox_model = QGroupBox('TreeView')  # Create a Group Box for the Model
    
            hbox_model = QHBoxLayout()  # Create a Horizontal layout for the Model
            vbox = QVBoxLayout()  # Create a Vertical layout for the Model Horizontal layout
    
            tree_view = QTreeView()  # Instantiate the View
    
            headers = ["Dictionary Keys", "Dictionary Values"]
    
            tree = {'Root': {"Level_1": {"Item_1": 1.10, "Item_2": 1.20, "Item_3": 1.30},
                             "Level_2": {"SubLevel_1":
                                             {"SubLevel_1_item1": 2.11, "SubLevel_1_Item2": 2.12, "SubLevel_1_Item3": 2.13},
                                         "SubLevel_2":
                                             {"SubLevel_2_Item1": 2.21, "SubLevel_2_Item2": 2.22,
                                              "SubLevel_2_Item3": 2.23}},
                             "Level_3": {"Item_1": 3.10, "Item_2": 3.20, "Item_3": 3.30}}}
    
            # Set the models
            model = TreeModel(headers, tree)
            tree_view.setModel(model)
            tree_view.expandAll()
            tree_view.resizeColumnToContents(0)
    
            hbox_model.addWidget(tree_view)  # Add the Widget to the Model Horizontal layout
            groupbox_model.setLayout(hbox_model)  # Add the hbox_model to layout of group box
            vbox.addWidget(groupbox_model)  # Add groupbox elements to vbox
            self.setLayout(vbox)
    
    
    class TreeModel(QAbstractItemModel):
        def __init__(self, headers, data, parent=None):
            super(TreeModel, self).__init__(parent)
            """ subclassing the standard interface item models must use and 
                    implementing index(), parent(), rowCount(), columnCount(), and data()."""
    
            rootData = [header for header in headers]
            self.rootItem = TreeNode(rootData)
            indent = -1
            self.parents = [self.rootItem]
            self.indentations = [0]
            self.createData(data, indent)
    
        def createData(self, data, indent):
            if type(data) == dict:
                indent += 1
                position = 4 * indent
                for dict_keys, dict_values in data.items():
                    if position > self.indentations[-1]:
                        if self.parents[-1].childCount() > 0:
                            self.parents.append(self.parents[-1].child(self.parents[-1].childCount() - 1))
                            self.indentations.append(position)
                    else:
                        while position < self.indentations[-1] and len(self.parents) > 0:
                            self.parents.pop()
                            self.indentations.pop()
                    parent = self.parents[-1]
                    parent.insertChildren(parent.childCount(), 1, parent.columnCount())
                    parent.child(parent.childCount() - 1).setData(0, dict_keys)
                    if type(dict_values) != dict:
                        parent.child(parent.childCount() - 1).setData(1, str(dict_values))
                    self.createData(dict_values, indent)
    
        def index(self, row, column, index=QModelIndex()):
            """ Returns the index of the item in the model specified by the given row, column and parent index """
    
            if not self.hasIndex(row, column, index):
                return QModelIndex()
            if not index.isValid():
                item = self.rootItem
            else:
                item = index.internalPointer()
    
            child = item.child(row)
            if child:
                return self.createIndex(row, column, child)
            return QModelIndex()
    
        def parent(self, index):
            """ Returns the parent of the model item with the given index
                    If the item has no parent, an invalid QModelIndex is returned """
    
            if not index.isValid():
                return QModelIndex()
            item = index.internalPointer()
            if not item:
                return QModelIndex()
    
            parent = item.parentItem
            if parent == self.rootItem:
                return QModelIndex()
            else:
                return self.createIndex(parent.childNumber(), 0, parent)
    
        def rowCount(self, index=QModelIndex()):
            """ Returns the number of rows under the given parent
                    When the parent is valid it means that rowCount is returning the number of children of parent """
    
            if index.isValid():
                parent = index.internalPointer()
            else:
                parent = self.rootItem
            return parent.childCount()
    
        def columnCount(self, index=QModelIndex()):
            """ Returns the number of columns for the children of the given parent """
    
            return self.rootItem.columnCount()
    
        def data(self, index, role=Qt.DisplayRole):
            """ Returns the data stored under the given role for the item referred to by the index """
    
            if index.isValid() and role == Qt.DisplayRole:
                return index.internalPointer().data(index.column())
            elif not index.isValid():
                return self.rootItem.data(index.column())
    
        def headerData(self, section, orientation, role=Qt.DisplayRole):
            """ Returns the data for the given role and section in the header with the specified orientation """
    
            if orientation == Qt.Horizontal and role == Qt.DisplayRole:
                return self.rootItem.data(section)
    
    
    class TreeNode(object):
        def __init__(self, data, parent=None):
            self.parentItem = parent
            self.itemData = data
            self.children = []
    
        def child(self, row):
            return self.children[row]
    
        def childCount(self):
            return len(self.children)
    
        def childNumber(self):
            if self.parentItem is not None:
                return self.parentItem.children.index(self)
    
        def columnCount(self):
            return len(self.itemData)
    
        def data(self, column):
            return self.itemData[column]
    
        def insertChildren(self, position, count, columns):
            if position < 0 or position > len(self.children):
                return False
            for row in range(count):
                data = [v for v in range(columns)]
                item = TreeNode(data, self)
                self.children.insert(position, item)
    
        def parent(self):
            return self.parentItem
    
        def setData(self, column, value):
            if column < 0 or column >= len(self.itemData):
                return False
            self.itemData[column] = value
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        app.setStyle("plastique")  # ("cleanlooks")
        form = GUIWindow()
        form.show()
        sys.exit(app.exec_())
    
    #/usr/bin/env python
    #-*-编码:utf-8-*-
    导入系统
    从PySide2.qtwidts导入QApplication、QWidget、QGroupBox、QHBoxLayout、QVBoxLayout、QTreeView
    从PySide2.QtCore导入Qt、qabstractemmodel、QModelIndex
    类GUI窗口(QWidget):
    def uuu init uuu(self,parent=None):
    超级(GUIWindow,self)。\uuuu init\uuuu(父级)
    “安装界面”
    self.setWindowTitle(“来自字典的QTreeView”)
    groupbox_model=QGroupBox('TreeView')#为模型创建一个分组框
    hbox_model=QHBoxLayout()#为模型创建水平布局
    vbox=QVBoxLayout()#为模型水平布局创建垂直布局
    tree_view=QTreeView()#实例化视图
    headers=[“字典键”,“字典值”]
    tree={'Root':{“Level_1”:{“Item_1”:1.10,“Item_2”:1.20,“Item_3”:1.30},
    “二级”:{“一级以下”:
    {“次级项目1”:2.11,“次级项目2”:2.12,“次级项目3”:2.13},
    “次级2”:
    {“次级项目1”:2.21,“次级项目2”:2.22,
    “次级项目3”:2.23},
    “第三级”:{“第1项”:3.10,“第2项”:3.20,“第3项”:3.30}}
    #树立榜样
    模型=树模型(标题、树)
    树视图.集合模型(模型)
    树视图。expandAll()
    树视图。调整ColumnToContent的大小(0)
    hbox_model.addWidget(树视图)#将小部件添加到模型水平布局中
    groupbox_模型。setLayout(hbox_模型)#将hbox_模型添加到group box的布局中
    vbox.addWidget(groupbox#U模型)#将groupbox元素添加到vbox
    self.setLayout(vbox)
    类树模型(QAbstractItemModel):
    def uuu init uuuu(self,header,data,parent=None):
    super(树模型,self)。\uuuu init\uuuuu(父级)
    “”“子类化标准接口项模型必须使用和
    正在实现索引()、父项()、行计数()、列计数()和数据()
    rootData=[标头中标头的标头]
    self.rootItem=TreeNode(rootData)
    缩进=-1
    self.parents=[self.rootItem]
    self.indentations=[0]
    self.createData(数据,缩进)
    def createData(自身、数据、缩进):
    如果类型(数据)=dict:
    缩进+=1
    位置=4*缩进
    对于dict_键,data.items()中的dict_值:
    如果位置>自缩进[-1]:
    如果self.parents[-1].childCount()>0:
    self.parents.append(self.parents[-1].child(self.parents[-1].childCount()-1))
    self.indentations.append(位置)
    其他:
    而位置0:
    self.parents.pop()
    self.indentations.pop()
    父母=自己。父母[-1]
    parent.insertChildren(parent.childCount(),1,parent.columnCount())
    parent.child(parent.childCount()-1).setData(0,dict_键)
    如果类型(dict_值)!=格言:
    parent.child(parent.childCount()-1).setData(1,str(dict_值))
    self.createData(dict_值,缩进)
    def索引(self,row,column,index=QModelIndex()):
    “”“返回给定行、列和父索引指定的模型中项的索引”“”
    如果不是self.hasIndex(行、列、索引):
    返回QModelIndex()
    如果不是index.isValid():
    item=self.rootItem
    其他:
    item=index.internalPointer()
    子项=项。子项(行)
    如果是儿童:
    返回self.createIndex(行、列、子级)
    返回QModelIndex()
    def父级(自我,索引):
    “”“返回具有给定索引的模型项的父项。”
    如果该项没有父项,则返回无效的QModelIndex“”
    如果不是index.isValid():
    返回QModelIndex()
    item=index.internalPointer()
    如果不是项目:
    返回QModelIndex()
    父项=项。父项
    如果父项==self.rootItem:
    返回QModelIndex()
    其他:
    返回self.createIndex(parent.childNumber(),0,parent)
    def行数(self,index=QModelIndex()):
    “”“返回给定父项下的行数
    当父级有效时,表示rowCount返回父级“”的子级数
    如果index.isValid():
    parent=index.internalPointer()
    其他:
    父项=self.rootItem
    返回parent.childCount()
    def columnCount(self,index=QModelIndex()):
    “”“返回给定父级的子级的列数”“”
    返回self.rootItem.columnCount()
    def数据(self,index,role=Qt.DisplayRole):
    “”“为索引引用的项返回存储在给定角色下的数据”“”
    如果index.isValid()和role==Qt.DisplayRole:
    返回index.internalPointer().data(index.column())
    elif不是索引。isValid():
    返回self.rootItem.data(index.column())
    def headerData(自身、部分、方向、角色=Qt.DisplayRole):
    “”“返回标头中具有指定方向的给定角色和节的数据”