Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Pyside使用列表填充QTreeView_Python_List_Pyside_Qtreeview_Qabstractitemmodel - Fatal编程技术网

Python Pyside使用列表填充QTreeView

Python Pyside使用列表填充QTreeView,python,list,pyside,qtreeview,qabstractitemmodel,Python,List,Pyside,Qtreeview,Qabstractitemmodel,我现在找了一段时间,找不到一个满意的答案来回答我的问题。我需要在QTreeView中表示一个列表: 例如: ['.', ['A', 'B', 'C', 'D', 'E', 'F']], ['A', ['G', 'H']], ['A\\G', []], ['A\\H', ['K', 'L']], ['A\\G\\K', []], ['A\\G\\L', []], ['B', ['I', 'J']], ['B\\I', []], ['B\\J', []], ['C', []], ['D', []],

我现在找了一段时间,找不到一个满意的答案来回答我的问题。我需要在QTreeView中表示一个列表:

例如:

['.', ['A', 'B', 'C', 'D', 'E', 'F']], ['A', ['G', 'H']], ['A\\G', []], ['A\\H', ['K', 'L']], ['A\\G\\K', []], ['A\\G\\L', []], ['B', ['I', 'J']], ['B\\I', []], ['B\\J', []], ['C', []], ['D', []], ['E', []], ['F', ['M']], ['F\\M', []]
应该这样表示:

.
|____A
     |____H
     |____G
          |____K
          |____L
|____B
     |____I
     |____J
|____C
|____D
|____E
|____F
     |____M
编辑:可能数据准备得不好。我也可以选择这种结构:

[".", "A", "A\\G", "A\\H", "A\\H\\K", "A\\H\\L", "B", "B\\I", "B\\J", "C", "D", "E", "F", "F\\M"]
在控制台中可视化该结构不是一个问题,但我不会将其用于treeview。 这是我的节点类和树模型

from PySide.QtCore import *
from PySide.QtGui import *
import sys


class Node(object):
    def __init__(self, name, parent=None):
        self._name = name
        self._children = []
        self._parent = parent

        if parent is not None:
            parent.add_child(self)

    def type_info(self):
        return 'NODE'

    def add_child(self, child):
        self._children.append(child)

    def insert_child(self, position, child):
        if position < 0 or position > len(self._children):
            return False

        self._children.insert(position, child)
        child._parent = self
        return True

    def remove_child(self, position):
        if position < 0 or position > len(self._children):
            return False

        child = self._children.pop(position)
        child._parent = None
        return True

    def name(self):
        return self._name

    def set_name(self, name):
        self._name = name

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

    def child_count(self):
        return len(self._children)

    def parent(self):
        return self._parent

    def row(self):
        if self._parent is not None:
            return self._parent._children.index(self)

    def log(self, tab_level=-1):
        output = ''
        tab_level += 1

        for i in range(tab_level):
            output += '\t'

        output += '|____' + self._name + '\n'

        for child in self._children:
            output += child.log(tab_level)

        tab_level -= 1

        return output

    def __repr__(self):
        return self.log()


class TemplateTreeModel(QAbstractItemModel):
    def __init__(self, root, parent=None):
        super(TemplateTreeModel, self).__init__(parent)
        self._root_node = root

    def rowCount(self, parent):
        if not parent.isValid():
            parent_node = self._root_node
        else:
            parent_node = parent.internalPointer()

        return parent_node.child_count()

    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        if not index.isValid():
            print('root')
            return None

        node = index.internalPointer()

        if role == Qt.DisplayRole or role == Qt.EditRole:
            if index.column() == 0:
                return node.name()

        if role == Qt.DecorationRole:
            if index.column() == 0:
                type_info = node.type_info()

                if type_info == 'FOLDER':
                    return QIcon('src/dir.png')

    def setData(self, index, value, role=Qt.EditRole):
        if index.isValid():
            if role == Qt.EditRole:
                node = index.internalPointer()
                node.set_name(value)

                return True
        return False

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole:
            if section == 0:
                return 'Templates'
            else:
                return 'Type'

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable

    def parent(self, index):
        node = self.get_node(index)
        parent_node = node.parent()

        if parent_node == self._root_node:
            return QModelIndex()

        return self.createIndex(parent_node.row(), 0, parent_node)

    def index(self, row, column, parent):
        parent_node = self.get_node(parent)

        child_item = parent_node.child(row)

        if child_item:
            return self.createIndex(row, column, child_item)
        else:
            return QModelIndex

    def get_node(self, index):
        if index.isValid():
            node = index.internalPointer()
            if node:
                return node
        return self._root_node

    def insertRows(self, position, rows, parent=QModelIndex()):
        parent_node = self.get_node(parent)
        self.beginInsertRows(parent, position, position + rows - 1)

        for row in range(rows):
            child_count = parent_node.child_count()
            child_node = Node('untitled' + str(child_count))
            success = parent_node.insert_child(position, child_node)

        self.endInsertRows()

        return success

    def removeRows(self, position, rows, parent=QModelIndex()):
        parent_node = self.get_node(parent)
        self.beginRemoveRows(parent, position, position + rows - 1)

        for row in range(rows):
            success = parent_node.remove_child(position)

        self.endRemoveRows()

        return success
对于控制台可视化,我将这样做。大概;)
谢谢

首先,您的模型在某些部分实现不正确,例如根是一个不可见的元素,因此我们必须添加它,等等,因此我修改了您的代码,并添加了一些方法,如下所示:

from PySide import QtCore, QtGui

class Node(object):
    def __init__(self, name="", parent=None):
        self._parent = parent
        self._name = name
        self._children = []

    def children(self):
        return self._children

    def hasChildren(self):
        return bool(self.children())

    def parent(self):
        return self._parent

    def name(self):
        return self._name

    def set_name(self, name):
        self._name = name

    def type_info(self):
        return 'NODE'

    def columnCount(self):
        return 1

    def child_count(self):
        return len(self._children)

    def add_child(self, child):
        self._children.append(child)
        child._parent = self

    def insert_child(self, position, child):
        if 0 <= position < child_count:
            self._children.insert(position, child)
            child._parent = self
            return True
        return False

    def remove_child(self, position):
        if 0 <= position < len(self._children):
            child = self._children.pop(position)
            child._parent = None
            return True
        return False

    def child(self, row):
        if 0 <= row < self.child_count():
            return self._children[row]

    def row(self):
        if self._parent is not None:
            return self._parent._children.index(self)
        return -1

    def find_child_by_name(self, name):
        for child in self._children:
            if child.name() == name:
                return child
        return None

    def log(self, tab_level=-1):
        output = ''
        tab_level += 1

        for i in range(tab_level):
            output += '\t'

        output += '|____' + self._name + '\n'

        for child in self._children:
            output += child.log(tab_level)

        tab_level -= 1

        return output

    def __repr__(self):
        return self.log()


class TemplateTreeModel(QtCore.QAbstractItemModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._root_node = Node()

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            if section == 0:
                return 'Templates'
            else:
                return 'Type'

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()
        node = parent.internalPointer() if parent.isValid() else self._root_node
        if node.children:
            return self.createIndex(row, column, node.child(row))
        else:
            return QtCore.QModelIndex()

    def parent(self, child):
        if not child.isValid():
            return QtCore.QModelIndex()
        node = child.internalPointer()
        if node.row() >= 0:
            return self.createIndex(node.row(), 0, node.parent())
        return QtCore.QModelIndex()

    def rowCount(self, parent=QtCore.QModelIndex()):
        node = parent.internalPointer() if parent.isValid() else self._root_node
        return node.child_count()

    def columnCount(self, parent=QtCore.QModelIndex()):
        return 1

    def hasChildren(self, parent= QtCore.QModelIndex()):
        node = parent.internalPointer() if parent.isValid() else self._root_node
        return node.hasChildren()

    def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole):
        if index.isValid() and role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole, ):
            node = index.internalPointer()
            print(node)
            return node.name()

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if role in (QtCore.Qt.EditRole,):
            node = index.internalPointer()
            node.set_name(value)
            self.dataChanged.emit(index, index)
            return True
        return False

    def flags(self, index: QtCore.QModelIndex):
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable

    def indexFromItem(self, it):
        root_index = QtCore.QModelIndex()
        if isinstance(it, Node):
            parents = []
            while it is not self._root_node:
                parents.append(it)
                it = it.parent()
            root = self._root_node
            for parent in reversed(parents):
                root = root.find_child_by_name(parent.name())
                root_index =self.index(root.row(), 0, root_index)
        return root_index

    def item_from_path(self, path, sep):
        depth = path.split(sep)
        root = self._root_node
        for d in depth:
            root = root.find_child_by_name(d)
            if root is None: return None
        return root

    def appendRow(self, item, parent=None):
        self.appendRows([item], parent)

    def appendRows(self, items, parent=None):
        if isinstance(items, list):
            ix = self.indexFromItem(parent)
            self.insertRows(self.rowCount(ix), items, parent)

    def insertRows(self, position, items, parent=None):
        parent_index = self.indexFromItem(parent)
        self.beginInsertRows(parent_index, position, position + len(items) - 1)
        if parent is None:
            parent = self._root_node
        for item in items:
            parent.add_child(item)
        self.endInsertRows()

ah dammit;)只是我忘记编辑掉的Node类的一个子类;)谢谢你的反馈。它的编辑你是男人!!!非常感谢。你甚至加强了我的工作;)这一行:model.appendRows([Node(_dir)代表dirs中的_dir],它)确实是让我头痛的一件事^^^只是一个小问题。如果我想更改显示的根的标签,如何正确地进行更改。只是将model.appendRow(Node(“.”)更改为model.appendRow(Node(“ROOT”))不起作用……它更改了名称,但结构也断了。更改
structure\u list=[”、
-->
structure\u list=['ROOT'、
ROOT.startswith(“.”和
model.appendRow(Node(“.”)
-->
model.appendRow(节点(“根”)
,和
ROOT=“.”+os.sep+ROOT
-->
ROOT=“根”+os.sep+root
。我建议您花点时间分析我的逻辑我明白了,这一切都是相关的。我还没有看透,还在学习。我会非常彻底地分析逻辑…通过阅读您的改进已经学到了一两件事;)thxmate@zwusel好吧,继续这样做,完善代码,让你理解整个逻辑,不是吗在我的问题中解释一下,因为这会花费太多时间。
from PySide import QtCore, QtGui

class Node(object):
    def __init__(self, name="", parent=None):
        self._parent = parent
        self._name = name
        self._children = []

    def children(self):
        return self._children

    def hasChildren(self):
        return bool(self.children())

    def parent(self):
        return self._parent

    def name(self):
        return self._name

    def set_name(self, name):
        self._name = name

    def type_info(self):
        return 'NODE'

    def columnCount(self):
        return 1

    def child_count(self):
        return len(self._children)

    def add_child(self, child):
        self._children.append(child)
        child._parent = self

    def insert_child(self, position, child):
        if 0 <= position < child_count:
            self._children.insert(position, child)
            child._parent = self
            return True
        return False

    def remove_child(self, position):
        if 0 <= position < len(self._children):
            child = self._children.pop(position)
            child._parent = None
            return True
        return False

    def child(self, row):
        if 0 <= row < self.child_count():
            return self._children[row]

    def row(self):
        if self._parent is not None:
            return self._parent._children.index(self)
        return -1

    def find_child_by_name(self, name):
        for child in self._children:
            if child.name() == name:
                return child
        return None

    def log(self, tab_level=-1):
        output = ''
        tab_level += 1

        for i in range(tab_level):
            output += '\t'

        output += '|____' + self._name + '\n'

        for child in self._children:
            output += child.log(tab_level)

        tab_level -= 1

        return output

    def __repr__(self):
        return self.log()


class TemplateTreeModel(QtCore.QAbstractItemModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._root_node = Node()

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            if section == 0:
                return 'Templates'
            else:
                return 'Type'

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()
        node = parent.internalPointer() if parent.isValid() else self._root_node
        if node.children:
            return self.createIndex(row, column, node.child(row))
        else:
            return QtCore.QModelIndex()

    def parent(self, child):
        if not child.isValid():
            return QtCore.QModelIndex()
        node = child.internalPointer()
        if node.row() >= 0:
            return self.createIndex(node.row(), 0, node.parent())
        return QtCore.QModelIndex()

    def rowCount(self, parent=QtCore.QModelIndex()):
        node = parent.internalPointer() if parent.isValid() else self._root_node
        return node.child_count()

    def columnCount(self, parent=QtCore.QModelIndex()):
        return 1

    def hasChildren(self, parent= QtCore.QModelIndex()):
        node = parent.internalPointer() if parent.isValid() else self._root_node
        return node.hasChildren()

    def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole):
        if index.isValid() and role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole, ):
            node = index.internalPointer()
            print(node)
            return node.name()

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if role in (QtCore.Qt.EditRole,):
            node = index.internalPointer()
            node.set_name(value)
            self.dataChanged.emit(index, index)
            return True
        return False

    def flags(self, index: QtCore.QModelIndex):
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable

    def indexFromItem(self, it):
        root_index = QtCore.QModelIndex()
        if isinstance(it, Node):
            parents = []
            while it is not self._root_node:
                parents.append(it)
                it = it.parent()
            root = self._root_node
            for parent in reversed(parents):
                root = root.find_child_by_name(parent.name())
                root_index =self.index(root.row(), 0, root_index)
        return root_index

    def item_from_path(self, path, sep):
        depth = path.split(sep)
        root = self._root_node
        for d in depth:
            root = root.find_child_by_name(d)
            if root is None: return None
        return root

    def appendRow(self, item, parent=None):
        self.appendRows([item], parent)

    def appendRows(self, items, parent=None):
        if isinstance(items, list):
            ix = self.indexFromItem(parent)
            self.insertRows(self.rowCount(ix), items, parent)

    def insertRows(self, position, items, parent=None):
        parent_index = self.indexFromItem(parent)
        self.beginInsertRows(parent_index, position, position + len(items) - 1)
        if parent is None:
            parent = self._root_node
        for item in items:
            parent.add_child(item)
        self.endInsertRows()
structure_list = ['.', ['A', 'B', 'C', 'D', 'E', 'F']], ['A', ['G', 'H']], ['A\\G', []], ['A\\H', ['K', 'L']], ['A\\G\\K', []], ['A\\G\\L', []], ['B', ['I', 'J']], ['B\\I', []], ['B\\J', []], ['C', []], ['D', []], ['E', []], ['F', ['M']], ['F\\M', []]

if __name__ == '__main__':
    import os
    import sys

    app = QtGui.QApplication(sys.argv)
    w = QtGui.QTreeView()
    model = TemplateTreeModel()
    w.setModel(model)
    model.appendRow(Node("."))

    for root, dirs in structure_list:
        depth = root.split(os.sep)
        if not root.startswith("."):
            # append .\\,
            # by example if root is "A\\G" then the results is:
            # ".\\A\\G"
            root = "." + os.sep + root
        it = model.item_from_path(root, os.sep)
        model.appendRows([Node(_dir) for _dir in dirs], it)
    w.expandAll()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())