如何从.model中删除raw

时间:2014-09-16 00:08:15

标签: python qt pyqt

下面的代码会创建一个QListView。单击其项目应从.model()中删除它。当项目被删除时,会有IndexError: list index out of range。代码有什么问题?

enter image description here

import os,sys
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
elements={'Animals':{1:'Bison',2:'Panther',3:'Elephant'},'Birds':{1:'Duck',2:'Hawk',3:'Pigeon'},'Fish':{1:'Shark',2:'Salmon',3:'Piranha'}}

class Model(QtCore.QAbstractListModel):
    def __init__(self):
        QtCore.QAbstractListModel.__init__(self)
        self.items=[] 
        self.modelDict={}       

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

    def data(self, index, role):
        if index.isValid():
            if role==QtCore.Qt.ItemDataRole:
                key=str(index.data().toString())
                returnedValue=self.modelDict.get(key)
                return QtCore.QVariant(returnedValue) 

            elif role==QtCore.Qt.DisplayRole:
                row=index.row()
                itemTitle=self.items[row]
                return QtCore.QVariant(itemTitle) 

    def addItems(self):
        for key in self.modelDict:
            index=QtCore.QModelIndex()
            self.beginInsertRows(index, 0, 0)
            self.items.append(key)

            inst=self.modelDict.get(key)
            self.setData(index, QtCore.QVariant(inst), QtCore.Qt.DisplayRole)            

        self.endInsertRows()        

    def removeByIndex(self, index):
        if index.isValid():
            row=index.row()        
            self.beginRemoveRows(QtCore.QModelIndex(), row, 0)
            self.items=[each for i,each in enumerate(self.items[:]) if i!=row]
            self.endRemoveRows()

class ListView(QtGui.QListView):
    def __init__(self):
        super(ListView, self).__init__()
        self.model= Model()
        self.model.modelDict=elements
        self.model.addItems()
        self.setModel(self.model)
        self.clicked.connect(self.itemClicked)
        self.show()

    def itemClicked(self, index):
        itemTitle=self.model.data(index, QtCore.Qt.DisplayRole).toString()
        itemData=self.model.data(index, QtCore.Qt.ItemDataRole).toPyObject()
        print 'itemTitle: "%s" itemData: %s'%(itemTitle,itemData)
        self.model.removeByIndex(index)


window=ListView()
sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:1)

您正在删除行而不更新rowCount;后来这导致你没有提供数据的空元素。这是有效的(请注意,为了简单起见,我删除了QVariants):

class Model(QtCore.QAbstractListModel):
    def __init__(self):
        QtCore.QAbstractListModel.__init__(self)
        self.items=[] 
        self.modelDict={}       

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

    def data(self, index, role):
        if index.isValid():
            if role==QtCore.Qt.ItemDataRole:
                key=str(index.data().toString())
                returnedValue=self.modelDict.get(key)
                return QtCore.QVariant(returnedValue) 

            elif role==QtCore.Qt.DisplayRole:
                row=index.row()
                itemTitle=self.items[row]
                return itemTitle

    def addItems(self):
        for key in self.modelDict:
            index=QtCore.QModelIndex()
            self.beginInsertRows(index, 0, 0)
            self.items.append(key)

            inst=self.modelDict.get(key)
            self.setData(index, inst, QtCore.Qt.DisplayRole)            

        self.endInsertRows()        

    def removeByIndex(self, index):
        if index.isValid():
            row=index.row()        
            self.beginRemoveRows(QtCore.QModelIndex(), row, 0)
            self.items=[each for i,each in enumerate(self.items[:]) if i!=row]
            self.endRemoveRows()

class ListView(QtGui.QListView):
    def __init__(self):
        super(ListView, self).__init__()
        self.model= Model()
        self.model.modelDict=elements
        self.model.addItems()
        self.setModel(self.model)
        self.clicked.connect(self.itemClicked)
        self.show()

    def itemClicked(self, index):
        itemTitle=str(self.model.data(index, QtCore.Qt.DisplayRole))
        print 'itemTitle: "%s"'%(itemTitle)
        self.model.removeByIndex(index)