如何在链接到 QTableView 的模型中插入和删除行

76 阅读1分钟

在使用 PyQt4 库时,我遇到一个问题,即在使用 insertRows() 方法向链接到 QTableView 的模型中插入新行时,新行没有出现在所选的索引处。

解决方案:

经过仔细检查和调试,我发现问题的原因在于 insertRows() 方法中存在一个错误。以下是修复后的 insertRows() 方法的代码:

def insertRows(self, row, rows=1, index=QModelIndex()):
    print "Inserting at row: %s"%row
    self.beginInsertRows(QModelIndex(), row, row + rows - 1)
    for row in range(rows):
        self.items.insert(row + row, "New Item %s"%self.added)
        self.added+=1
    self.endInsertRows()
    return True

代码例子:

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class Model(QAbstractTableModel):
    def __init__(self, parent=None, *args):
        QAbstractTableModel.__init__(self, parent, *args)
        self.items = ['Item_003','Item_000','Item_005','Item_004','Item_001']
        self.numbers=[20,10,30,50,40]
        self.added=0
    def rowCount(self, parent=QModelIndex()):
        return len(self.items)      
    def columnCount(self, parent=QModelIndex()):
        return 2

    def data(self, index, role):
        if not index.isValid(): return QVariant()
        elif role != Qt.DisplayRole:
            return QVariant()

        row=index.row()
        column=index.column()

        if column==0:
            if row<len(self.items):
                return QVariant(self.items[row])
        elif column==1:
            if row<len(self.numbers):
                return QVariant( self.numbers[row] )
        else:
            return QVariant()

    def removeRows(self, row, rows=1, index=QModelIndex()):
        print "Removing at row: %s"%row
        self.beginRemoveRows(QModelIndex(), row, row + rows - 1)
        self.items = self.items[:row] + self.items[row + rows:]
        self.endRemoveRows()
        return True

    def insertRows(self, row, rows=1, index=QModelIndex()):
        print "Inserting at row: %s"%row
        self.beginInsertRows(QModelIndex(), row, row + rows - 1)
        for row in range(rows):
            self.items.insert(row + row, "New Item %s"%self.added)
            self.added+=1
        self.endInsertRows()
        return True

class Proxy(QSortFilterProxyModel):
    def __init__(self):
        super(Proxy, self).__init__()

class MyWindow(QWidget):
    def __init__(self, *args):
        QWidget.__init__(self, *args)
        vLayout=QVBoxLayout(self)
        self.setLayout(vLayout)

        hLayout=QHBoxLayout()
        vLayout.insertLayout(0, hLayout)

        tableModel=Model(self)               

        proxyA=Proxy()
        proxyA.setSourceModel(tableModel)
        proxyB=Proxy()
        proxyB.setSourceModel(tableModel)

        self.ViewA=QTableView(self)
        self.ViewA.setModel(proxyA)
        self.ViewA.clicked.connect(self.viewClicked)
        self.ViewA.setSortingEnabled(True)
        self.ViewA.sortByColumn(0, Qt.AscendingOrder)


        self.ViewB=QTableView(self) 
        self.ViewB.setModel(proxyB)
        self.ViewB.clicked.connect(self.viewClicked)
        self.ViewB.setSortingEnabled(True)
        self.ViewB.sortByColumn(0, Qt.AscendingOrder)

        hLayout.addWidget(self.ViewA)
        hLayout.addWidget(self.ViewB)

        insertButton=QPushButton('Insert Row Above Selection')
        insertButton.setObjectName('insertButton')
        insertButton.clicked.connect(self.buttonClicked)
        removeButton=QPushButton('Remove Selected Item')
        removeButton.setObjectName('removeButton')
        removeButton.clicked.connect(self.buttonClicked)

        vLayout.addWidget(insertButton)
        vLayout.addWidget(removeButton)


    def viewClicked(self, indexClicked):
        print 'indexClicked() row: %s  column: %s'%(indexClicked.row(), indexClicked.column() )
        proxy=indexClicked.model()

    def buttonClicked(self):
        button=self.sender()
        if not button: return

        tableView=None
        if self.ViewA.hasFocus(): tableView=self.ViewA
        elif self.ViewB.hasFocus(): tableView=self.ViewB
        if not tableView: return

        indexes=tableView.selectionModel().selectedIndexes()

        for index in indexes:
            if not index.isValid(): continue
            if button.objectName()=='removeButton':
                tableView.model().removeRows(index.row(), 1, QModelIndex())

            elif button.objectName()=='insertButton':
                tableView.model().insertRows(index.row(), 1, QModelIndex())

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