【问题标题】:Insert and remove items from a QAbstractListModel从 QAbstractListModel 中插入和删除项目
【发布时间】:2014-01-17 04:33:47
【问题描述】:

我正在尝试创建一个 QAbstractListView 以与 QComboBox 一起使用,该 QComboBox 维护其包含的项目的排序列表。我在下面包含了一些示例代码来说明我的问题。当我更新列表中的项目时,组合框的 currentIndex 不会更新以反映对模型的更改。我尝试使用 rowsAboutToBeInserted 和 rowsInserted 信号,但看不到任何效果(也许我做错了?)。

我的实际用例稍微复杂一些,但例子应该足够了。被排序的项目不仅仅是字符串,而且需要更多的努力来排序,并且 ItemDataRole 与它们的 DisplayRole 不同。

itemsAdded 和 itemsRemoved 是我自己的函数,它们将连接到我尝试代理的另一个列表的信号。

要触发问题,请按“插入“c”按钮。字符串被正确插入到列表中,但选择从“e”移动到“d”(即选择索引没有改变)。

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

from PyQt4 import QtCore, QtGui

class Model(QtCore.QAbstractListModel):
    def __init__(self, *args, **kwargs):
        QtCore.QAbstractListModel.__init__(self, *args, **kwargs)
        self.items = []

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if index.isValid() is True:
            if role == QtCore.Qt.DisplayRole:
                return QtCore.QVariant(self.items[index.row()])
            elif role == QtCore.Qt.ItemDataRole:
                return QtCore.QVariant(self.items[index.row()])
        return QtCore.QVariant()

    def itemsAdded(self, items):
        # insert items into their sorted position
        items = sorted(items)
        row = 0
        while row < len(self.items) and len(items) > 0:
            if items[0] < self.items[row]:
                self.items[row:row] = [items.pop(0)]
                row += 1
            row += 1
        # add remaining items to end of list
        if len(items) > 0:
            self.items.extend(items)

    def itemsRemoved(self, items):
        # remove items from list
        for item in items:
            for row in range(0, len(self.items)):
                if self.items[row] == item:
                    self.items.pop(row)
                    break

def main():
    app = QtGui.QApplication([])
    w = QtGui.QWidget()
    w.resize(300,300)
    layout = QtGui.QVBoxLayout()

    model = Model()
    model.itemsAdded(['a','b','d','e'])

    combobox = QtGui.QComboBox()
    combobox.setModel(model)
    combobox.setCurrentIndex(3)
    layout.addWidget(combobox)

    def insertC(self):
        model.itemsAdded('c')

    button = QtGui.QPushButton('Insert "c"')
    button.clicked.connect(insertC)
    layout.addWidget(button)

    w.setLayout(layout)
    w.show()
    app.exec_()

if __name__ == '__main__':
    main()

【问题讨论】:

    标签: python qt pyqt4 qabstractlistmodel


    【解决方案1】:

    下面是一个完整的工作示例,基于 Tim 的回答。

    不需要调用 setCurrentIndex。当正确调用 insertRows/removeRows 时,视图会自动跟踪这一点。

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from PyQt4 import QtCore, QtGui
    
    class Model(QtCore.QAbstractListModel):
        def __init__(self, *args, **kwargs):
            QtCore.QAbstractListModel.__init__(self, *args, **kwargs)
            self.items = []
    
        def rowCount(self, parent=QtCore.QModelIndex()):
            return len(self.items)
    
        def data(self, index, role=QtCore.Qt.DisplayRole):
            if index.isValid() is True:
                if role == QtCore.Qt.DisplayRole:
                    return QtCore.QVariant(self.items[index.row()])
                elif role == QtCore.Qt.ItemDataRole:
                    return QtCore.QVariant(self.items[index.row()])
            return QtCore.QVariant()
    
        def itemsAdded(self, items):
            # insert items into their sorted position
            items = sorted(items)
            row = 0
            while row < len(self.items) and len(items) > 0:
                if items[0] < self.items[row]:
                    self.beginInsertRows(QtCore.QModelIndex(), row, row)
                    self.items.insert(row, items.pop(0))
                    self.endInsertRows()
                    row += 1
                row += 1
            # add remaining items to end of the list
            if len(items) > 0:
                self.beginInsertRows(QtCore.QModelIndex(), len(self.items), len(self.items) + len(items) - 1)
                self.items.extend(items)
                self.endInsertRows()
    
        def itemsRemoved(self, items):
            # remove items from the list
            for item in items:
                for row in range(0, len(self.items)):
                    if self.items[row] == item:
                        self.beginRemoveRows(QtCore.QModelIndex(), row, row)
                        self.items.pop(row)
                        self.endRemoveRows()
                        break
    
    def main():
        app = QtGui.QApplication([])
        w = QtGui.QWidget()
        w.resize(300,200)
        layout = QtGui.QVBoxLayout()
    
        model = Model()
        model.itemsAdded(['a','b','d','e'])
    
        combobox = QtGui.QComboBox()
        combobox.setModel(model)
        combobox.setCurrentIndex(3)
        layout.addWidget(combobox)
    
        def insertC(self):
            model.itemsAdded('c')
    
        def removeC(self):
            model.itemsRemoved('c')
    
        buttonInsert = QtGui.QPushButton('Insert "c"')
        buttonInsert.clicked.connect(insertC)
        layout.addWidget(buttonInsert)
    
        buttonRemove = QtGui.QPushButton('Remove "c"')
        buttonRemove.clicked.connect(removeC)
        layout.addWidget(buttonRemove)
    
        w.setLayout(layout)
        w.show()
        app.exec_()
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

      【解决方案2】:

      我猜你需要自己修改选择索引,即类似

      if row < currentIndex():
          setCurrentIndex( currentIndex() + 1 );
      

      不过你应该阅读following passage:

      为可调整大小的类似列表的数据结构提供接口的模型可以提供 insertRows() 和 removeRows() 的实现。在实现这些函数时,调用适当的函数很重要,以便所有连接的视图都知道任何更改:

      • insertRows() 实现必须在将新行插入数据结构之前调用 beginInsertRows(),之后必须立即调用 endInsertRows()。

      • removeRows() 实现必须在从数据结构中删除行之前调用 beginRemoveRows(),之后必须立即调用 endRemoveRows()。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-02
        • 1970-01-01
        • 2015-03-27
        • 2019-07-22
        • 2015-01-17
        相关资源
        最近更新 更多