代码之家  ›  专栏  ›  技术社区  ›  fredrik

如何使用qabstractemmodel从QTreeView中删除行?

  •  1
  • fredrik  · 技术社区  · 6 年前

    我正在尝试从模型中删除QTreeView项“Node 6(delete me)”。

    我无法让它工作,因为没有删除任何内容。我做错了什么?
    看到了吗 MainWindow.init 删除代码的方法。

    enter image description here

    import sys
    
    try:
        from PySide2 import QtWidgets
    except ImportError:
        from PyQt5 import QtWidgets
    
    try:
        from PySide2 import QtCore
    except ImportError:
        from PyQt5 import QtCore
    
    
    class Node(object):
        def __init__(self, name, parent=None):
            self._name = name
            self._children = []
            self._parent = parent
    
            if parent is not None:
                parent.addChild(self)
    
        def addChild(self, child):
            self._children.append(child)
            child._parent = self
    
        def name(self):
            return self._name
    
        def child(self, row):
            return self._children[row]
    
        def insertChild(self, position, child):
            if position < 0 or position > len(self._children):
                return False
    
            self._children.insert(position, child)
            child._parent = self
            return True
    
        def childCount(self):
            return len(self._children)
    
        def parent(self):
            return self._parent
    
        def setParent(self, new_parent):
            self._parent._children.remove(self)
            self._parent = new_parent
            new_parent._children.append(self)
    
        def row(self):
            if self._parent is not None:
                return self._parent._children.index(self)
    
        def removeChild(self, position):
            if position < 0 or position > len(self._children):
                return False
            child = self._children.pop(position)
            child._parent = None
            return True
    
        def __repr__(self):
            return self._name
    
    
    class TreeModel(QtCore.QAbstractItemModel):
        def __init__(self, root, parent=None):
            super(TreeModel, self).__init__(parent)
            self._rootNode = root
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            if not parent.isValid():
                parentNode = self._rootNode
            else:
                parentNode = parent.internalPointer()
    
            return parentNode.childCount()
    
        def columnCount(self, parent):
            return 1
    
        def data(self, index, role):
            """Return whatever the view should display"""
    
            if not index.isValid():
                return None
    
            node = index.internalPointer()
    
            if role == QtCore.Qt.DisplayRole:
                if index.column() == 0:
                    return node.name()
    
        def index(self, row, column, parent):
            if not parent.isValid():
                # parent is not valid when it is the root node, since the "parent"
                # method returns an empty QModelIndex
                parentNode = self._rootNode
            else:
                parentNode = parent.internalPointer()  # the node
    
            childItem = parentNode.child(row)
    
            return self.createIndex(row, column, childItem)
    
        def parent(self, index):
            node = index.internalPointer()
    
            parentNode = node.parent()
    
            if parentNode == self._rootNode:
                return QtCore.QModelIndex()
    
            return self.createIndex(parentNode.row(), 0, parentNode)
    
        def flags(self, index):
    
            # Original, inherited flags:
            original_flags = super(TreeModel, self).flags(index)
    
            return (original_flags | QtCore.Qt.ItemIsEnabled
                    | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled
                    | QtCore.Qt.ItemIsDropEnabled)
    
        def headerData(self, section, orientation, role):
            if role == QtCore.Qt.DisplayRole:
                if section == 0:
                    return 'Node name'
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            QtWidgets.QMainWindow.__init__(self)
    
            self.tree = QtWidgets.QTreeView()
            self.layout = QtWidgets.QGridLayout()
            self.main_widget = QtWidgets.QWidget()
    
            self.layout.addWidget(self.tree, 0, 0)
            self.main_widget.setLayout(self.layout)
            self.setCentralWidget(self.main_widget)
    
            # Note how these are added in a non-sorted fashion
            root_node = Node('Hidden root')
            Node(name='Node 3', parent=root_node)  # add using parent param
            n2 = Node(name='Node 2', parent=root_node)  # add using parent param
            Node(name='Node 1', parent=root_node)  # add using parent param
            n2.addChild(Node(name='Node 5'))  # add using addChild
            n2.addChild(Node(name='Node 6 (delete me)'))  # add using addChild
            n2.addChild(Node(name='Node 4'))  # add using addChild
    
            model = TreeModel(root=root_node)
            self.tree.setModel(model)
            self.tree.expandAll()
    
            # Attempt to remove a node from within the model
            node2 = model.index(1, 0, QtCore.QModelIndex())  # "Node 2" index
            index = model.index(1, 0, parent=node2)
            index_node = index.internalPointer()
            print('index represents node "%s" (its parent node is "%s")' %
                (index_node.name(), index.parent().internalPointer().name()))
            print('Removing %s on row %s' % (index_node.name(), index.row()))
            model.beginRemoveRows(index.parent(), index.row(), index.row())
            success = model.removeRow(index.row(), parent=index.parent())
            print('Removal was a succes?:', success)
            model.endRemoveRows()
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        main_window = MainWindow()
        main_window.show()
        sys.exit(app.exec_())
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   fredrik    6 年前

    @Jaa-c如果你喜欢,把这个复制粘贴到你自己的答案中,我会把它标记为已接受的答案。

    import sys
    
    try:
        from PySide2 import QtWidgets
    except ImportError:
        from PyQt5 import QtWidgets
    
    try:
        from PySide2 import QtCore
    except ImportError:
        from PyQt5 import QtCore
    
    
    class Node(object):
        def __init__(self, name, parent=None):
            self._name = name
            self._children = []
            self._parent = parent
    
            if parent is not None:
                parent.addChild(self)
    
        def addChild(self, child):
            self._children.append(child)
            child._parent = self
    
        def name(self):
            return self._name
    
        def child(self, row):
            return self._children[row]
    
        def insertChild(self, position, child):
            if position < 0 or position > len(self._children):
                return False
    
            self._children.insert(position, child)
            child._parent = self
            return True
    
        def childCount(self):
            return len(self._children)
    
        def parent(self):
            return self._parent
    
        def setParent(self, new_parent):
            self._parent._children.remove(self)
            self._parent = new_parent
            new_parent._children.append(self)
    
        def row(self):
            if self._parent is not None:
                return self._parent._children.index(self)
    
        def removeChild(self, position):
            if position < 0 or position > len(self._children):
                return False
            child = self._children.pop(position)
            child._parent = None
            return True
    
        def __repr__(self):
            return self._name
    
    
    class TreeModel(QtCore.QAbstractItemModel):
        def __init__(self, root, parent=None):
            super(TreeModel, self).__init__(parent)
            self._rootNode = root
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            if not parent.isValid():
                parentNode = self._rootNode
            else:
                parentNode = parent.internalPointer()
    
            return parentNode.childCount()
    
        def columnCount(self, parent):
            return 1
    
        def data(self, index, role):
            """Return whatever the view should display"""
    
            if not index.isValid():
                return None
    
            node = index.internalPointer()
    
            if role == QtCore.Qt.DisplayRole:
                if index.column() == 0:
                    return node.name()
    
        def index(self, row, column, parent):
            if not parent.isValid():
                # parent is not valid when it is the root node, since the "parent"
                # method returns an empty QModelIndex
                parentNode = self._rootNode
            else:
                parentNode = parent.internalPointer()  # the node
    
            childItem = parentNode.child(row)
    
            return self.createIndex(row, column, childItem)
    
        def parent(self, index):
            node = index.internalPointer()
    
            parentNode = node.parent()
    
            if parentNode == self._rootNode:
                return QtCore.QModelIndex()
    
            return self.createIndex(parentNode.row(), 0, parentNode)
    
        def flags(self, index):
    
            # Original, inherited flags:
            original_flags = super(TreeModel, self).flags(index)
    
            return (original_flags | QtCore.Qt.ItemIsEnabled
                    | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled
                    | QtCore.Qt.ItemIsDropEnabled)
    
        def headerData(self, section, orientation, role):
            if role == QtCore.Qt.DisplayRole:
                if section == 0:
                    return 'Node name'
    
        def removeRow(self, row, parent):
            if not parent.isValid():
                # parent is not valid when it is the root node, since the "parent"
                # method returns an empty QModelIndex
                parentNode = self._rootNode
            else:
                parentNode = parent.internalPointer()  # the node
    
            parentNode.removeChild(row)
            return True
    
    
    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self):
            QtWidgets.QMainWindow.__init__(self)
    
            self.tree = QtWidgets.QTreeView()
            self.layout = QtWidgets.QGridLayout()
            self.main_widget = QtWidgets.QWidget()
    
            self.layout.addWidget(self.tree, 0, 0)
            self.main_widget.setLayout(self.layout)
            self.setCentralWidget(self.main_widget)
    
            # Note how these are added in a non-sorted fashion
            root_node = Node('Hidden root')
            Node(name='Node 3', parent=root_node)  # add using parent param
            n2 = Node(name='Node 2', parent=root_node)  # add using parent param
            Node(name='Node 1', parent=root_node)  # add using parent param
            n2.addChild(Node(name='Node 5'))  # add using addChild
            n2.addChild(Node(name='Node 6 (delete me)'))  # add using addChild
            n2.addChild(Node(name='Node 4'))  # add using addChild
    
            model = TreeModel(root=root_node)
            self.tree.setModel(model)
            self.tree.expandAll()
    
            # Attempt to remove a node from within the model
            node2 = model.index(1, 0, QtCore.QModelIndex())  # "Node 2" index
            index = model.index(1, 0, parent=node2)
            index_node = index.internalPointer()
            print('index represents node "%s" (its parent node is "%s")' %
                (index_node.name(), index.parent().internalPointer().name()))
            print('Removing %s on row %s' % (index_node.name(), index.row()))
            model.beginRemoveRows(index.parent(), index.row(), index.row())
            success = model.removeRow(index.row(), parent=index.parent())
            print('Removal was a succes?:', success)
            model.endRemoveRows()
    
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        main_window = MainWindow()
        main_window.show()
        sys.exit(app.exec_())