PySide Qt 在叶项中插入行并更新视图

PySide Qt insert row at leaf item and update view

我有这个主要工作的代码,使用户能够将项目添加到树结构。只要您不向叶项(没有子项的项)添加项,这就可以正常工作。

如果项目没有子项目,那么在第一次添加子项目时,视图根本不会更新。您可以通过卷起父项并重新展开它来使视图更新。或者,添加第二个子项目会导致视图更新(您可以看到两个项目都已添加)。

如何在将第一个子项添加到叶项后更新视图?

更新:您也可以双击新的父项,将显示其子项,但不会显示扩展小部件。似乎没有发生的是在满足上述条件之一之前不会显示小的展开项目小部件。

from PySide import QtCore, QtGui
import sys


model_data = [
    [1, [2, [3, 4]]],
    [5, [6, 7]],
    [8, [9]],
    [10]
]


class MyData:

    def __init__(self, number, parent=None):
        ''''''
        self.number = number
        self.children = []
        self.parent = parent
        if parent is not None:
            parent.addChild(self)


    def row(self):
        ''''''
        row = None
        if self.parent is None:
            row = 0
        else:
            for i, item in enumerate(self.parent.children):
                if item == self:
                    row = i
                    break

        return row


    def addChild(self, item):
        ''''''
        self.children.append(item)
        item.parent = self


class TreeModel(QtCore.QAbstractItemModel):

    def __init__(self, top, *args, **kwargs):
        ''''''
        super(TreeModel, self).__init__(*args, **kwargs)
        self.__top = top


    def index(self, row, column, parent=QtCore.QModelIndex()):
        ''''''
        if parent.isValid():
            parent_node = parent.internalPointer()
            node = parent_node.children[row]
            index = self.createIndex(row, column, node)
        else:
            index = self.createIndex(row, column, self.__top)
        return index


    def parent(self, index):
        ''''''
        if index.isValid():
            node = index.internalPointer()
            parent = node.parent
            if parent is None:
                parent_index = QtCore.QModelIndex()
            else:
                parent_index = self.createIndex(parent.row(), 0, parent)
        else:
            parent_index = QtCore.QModelIndex()
        return parent_index


    def rowCount(self, index=QtCore.QModelIndex()):
        ''''''
        node = index.internalPointer()
        if node is None:
            count = 1
        else:
            count = len(node.children)
        return count


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


    def data(self, index, role=QtCore.Qt.DisplayRole):
        ''''''
        if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole:
            node = index.internalPointer()
            data = str(node.number)

        else:
            data = None

        return data


    def addChild(self, index, child):
        self.beginInsertRows(index, self.rowCount(index), self.rowCount(index)+1)

        parent = index.internalPointer()
        parent.addChild(child)

        self.endInsertRows()


class Window(QtGui.QMainWindow):

    def __init__(self):
        super(Window, self).__init__()

        self.build_model()

        self.add_item_action = QtGui.QAction('New &Item', self)
        self.add_item_action.triggered.connect(self.add_item)

        self.view = QtGui.QTreeView()
        self.view.setModel(self.model)

        self.setCentralWidget(self.view)
        self.show()


    def build_model(self):
        def recurse(parent, children_data):
            for child_data in children_data:
                if isinstance(child_data, list):
                    recurse(child, child_data)
                else:
                    child = MyData(child_data, parent=parent)

        top = MyData(0)                      
        for i, next in enumerate(model_data):
            recurse(top, next) 
        self.model = TreeModel(top)


    def add_item(self):
        ''''''
        index = self.view.currentIndex()
        new_item = MyData(0)
        self.model.addChild(index, new_item)


    def contextMenuEvent(self, event):
        ''''''
        contextMenu = QtGui.QMenu()
        contextMenu.addAction(self.add_item_action)
        contextMenu.exec_(event.globalPos())


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Window()
    sys.exit(app.exec_())

模型不会总是正确更新,除非它知道布局发生了变化。所以试试这个:

    def addChild(self, index, child):
        ...
        self.endInsertRows()
        self.layoutChanged.emit()