【问题标题】:Multi-level QTreeView多级 QTreeView
【发布时间】:2015-03-10 00:37:50
【问题描述】:

我很难理解如何使用 QTreeView 和 QStandardItemModel 设置多级 QTree。

这是我所拥有的:

from PySide.QtGui import *
import sys

class MainFrame(QWidget):
    def __init__(self):
        QWidget.__init__(self)

        tree = {'root': {
                    "1": ["A", "B", "C"],
                    "2": {
                        "2-1": ["G", "H", "I"],
                        "2-2": ["J", "K", "L"]},
                    "3": ["D", "E", "F"]}
        }

        self.tree = QTreeView(self)
        root_model = QStandardItemModel()
        self.tree.setModel(root_model)

        for r,root in enumerate(sorted(tree)):
            root_item = QStandardItem(root)
            root_model.setItem(r,root_item)

            for c,child in enumerate(sorted(tree[root])):
                child_model = QStandardItemModel(root_model)
                child_item = QStandardItem(child)
                child_model.setItem(c, child_item)

                for gc, grand_child in enumerate(sorted(tree[root][child])):
                    grand_child_model = QStandardItemModel(child_model)
                    grand_child_item = QStandardItem(grand_child)
                    grand_child_model.setItem(gc,grand_child_item)

                    if type(tree[root][child]) == dict:
                        for ggc, gran_grand_child in enumerate(sorted(tree[root][child][grand_child])):
                            gran_grand_child_model = QStandardItemModel(grand_child_model)
                            gran_grand_child_item = QStandardItem(gran_grand_child)
                            gran_grand_child_model.setItem(ggc, gran_grand_child_item)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = MainFrame()
    main.show()
    sys.exit(app.exec_())

我希望它看起来像这样:

到目前为止,只显示了“根”项目,它没有抛出任何错误。

另外,我制作这个 for 循环有点匆忙,它很难阅读/理解,因为它有太多嵌套的 for 循环。我想知道是否有更好的方法来根据初始字典扩展树。

【问题讨论】:

    标签: python model-view-controller pyqt pyside qtreeview


    【解决方案1】:

    您正在为每个项目创建一个模型。那是错误的。您应该在项目上使用.appendRow/.insertRow 来添加子项目。

    至于您的循环,我可能会使用递归方法来填充树。这是我要做的:

    from PySide.QtGui import *
    import sys
    import types
    
    class MainFrame(QWidget):
        def __init__(self):
            QWidget.__init__(self)
    
            tree = {'root': {
                        "1": ["A", "B", "C"],
                        "2": {
                            "2-1": ["G", "H", "I"],
                            "2-2": ["J", "K", "L"]},
                        "3": ["D", "E", "F"]}
            }
    
            self.tree = QTreeView(self)
            layout = QHBoxLayout(self)
            layout.addWidget(self.tree)
    
            root_model = QStandardItemModel()
            self.tree.setModel(root_model)
            self._populateTree(tree, root_model.invisibleRootItem())
    
        def _populateTree(self, children, parent):
            for child in sorted(children):
                child_item = QStandardItem(child)
                parent.appendRow(child_item)
                if isinstance(children, types.DictType):
                    self._populateTree(children[child], child_item)
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        main = MainFrame()
        main.show()
        sys.exit(app.exec_())
    

    PS:您也没有为主窗口使用任何布局。我在上面加了。

    PSv2:如果可能,最好避免在 python 中进行类型检查,但按照您构建 tree 的方式,这是必要的。如果你以不同的方式组织它会更好,比如dicts 可能:

    tree = {'root': {
                '1': {'A':{}, 'B':{}, 'C':{}},
                 ...
           }
    

    【讨论】:

    • 很棒,对递归的感觉很好,从没想过。
    • 你的递归循环作为一个不充分的停止规则,因为“孩子”总是被迭代(例如,将为字符串中的每个字符创建一个孩子)
    • @DanielBraun 仅当您使用{'foo': 'bar'} 而不是{'foo': ['bar']} 时。无论如何,这意味着一个伪代码,而不是一个实际的实现。不知道树结构就不能写树遍历。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    相关资源
    最近更新 更多