如何访问存储在QModelIndex中的数据

时间:2014-09-19 22:18:05

标签: python qt pyqt

下面的代码创建了一个QListView,其中包含数据和代理模型"附加"。 单击其中一个单选按钮可调用buttonClicked()功能。

此函数调用模型的.data(index,role)方法来获取存储在当前索引中的数据。

对于DisplayRole模型的.data()方法,正确返回索引的名称(在创建时分配给它)。但是当时 ' ItemDataRole'使用我收到错误:

TypeError: QSortFilterProxyModel.data(QModelIndex, int role=Qt.DisplayRole): argument 2 has unexpected type 'sip.enumtype'

-

Question 1: How to fix this error?

如果你看一下addItems()方法那里有一条线:

self.setData(index, 'keyword')

显然我正在尝试设置关键字'作为我自己的"自定义数据" (它是在过滤索引时将使用ProxyModel的吗?)。

问题2:如何查询字符串"关键字"我已经设置了self.setData(index, 'keyword')? 这些数据是否可访问,或者是"保留"并且无法查询?

enter image description here

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 ProxyModel(QtGui.QSortFilterProxyModel):
    def __init__(self, parent=None):
        super(ProxyModel, self).__init__(parent)

class DataModel(QtCore.QAbstractListModel):
    def __init__(self):
        QtCore.QAbstractListModel.__init__(self)
        self.items=[] 
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)
    def data(self, index, role):
        if not index.isValid() or not (0<=index.row()<len(self.items)):  return QtCore.QVariant()

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

        elif role==QtCore.Qt.ItemDataRole:
            return index.data()

    def addItems(self):
        for key in elements:
            index=QtCore.QModelIndex()
            self.setData(index, 'keyword')
            self.beginInsertRows(index, 0, 0)
            self.items.append(key)           

        self.endInsertRows()        

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        layout=QtGui.QVBoxLayout()
        self.setLayout(layout)        

        self.view=QtGui.QListView()

        self.dataModel=DataModel()        
        self.dataModel.addItems()

        self.proxyModel=ProxyModel()
        self.proxyModel.setSourceModel(self.dataModel)
        self.view.setModel(self.proxyModel)
        buttonsLayout=QtGui.QHBoxLayout()
        animalsButton=QtGui.QRadioButton('Show Animals')
        birdsButton=QtGui.QRadioButton('Show Birds')
        fishButton=QtGui.QRadioButton('Show Fish')
        self.buttons=[animalsButton,birdsButton,fishButton]
        for button in self.buttons:
            button.toggled.connect(self.buttonClicked)
            buttonsLayout.addWidget(button)      
        layout.addWidget(self.view)
        layout.insertLayout(1,buttonsLayout)
        self.show()

    def buttonClicked(self,arg=None):
        for button in self.buttons:
            if button.isChecked(): break

        index=self.view.currentIndex()
        print 'Index DisplayRole: %s'%self.view.model().data(index, QtCore.Qt.DisplayRole).toString() 
        # print 'ItemDataRole', self.view.model().data(index, QtCore.Qt.ItemDataRole)    

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

1 个答案:

答案 0 :(得分:5)

以下是有关如何使用QTableView填充QStandardItemModel填充QStandardItem的工作示例。

使用QtGui.QStandardItemModel优于QtCore.QAbstractListModel的一个明显优势是,QtGui.QStandardItemModel不必进行细分,以便分配到QTableView。 你只需继续宣布:

view=QtGui.QTableView() # declare table view
model=QtGui.QStandardItemModel() # declare model
view.setModel(model) # assign model to table view

创建一个视图项首先声明它:

item=QtGui.QStandardItem('My Item Name') # stored 'My Item Name' can be queried using `Qt.DisplayRole` flag

使用以下方式分配声明的QStandardItem进行查看:

model.appendRow(item)

model.appendRow(item)方法“创建”与表视图中的列一样多QModelIndex es。因此,无需为一行中的每一列手动创建QModelIndex es:项目分配给的行。

接下来,使用item.setData(value,role)方法,您可以使用预定义的QModelIndex角色之一存储任何类型的数据,例如:

item.setData('< Column 0 My Display Value as "DisplayRole" >', QtCore.Qt.DisplayRole)
item.setData('< Column 0 My Custom Value as "UserRole" >', QtCore.Qt.UserRole)
item.setData('< Column 0 My Custom Value as "UserRole+1" >', QtCore.Qt.UserRole+1)

上面的所有三个赋值行都用于为同一个“item”分配三个不同的值:第一个值是一个字符串'< Column 0 My Display Value as "DisplayRole" >',它存储在Qt.DisplayRole个角色下(使用此角色来检索它)背部)。

字符串值:'< Column 0 My Custom Value as "UserRole" >'存储在Qt.UserRole下。使用此角色将其检索回来。等等。

虽然item.setData(value,role)方法非常有用并且确实使用了简单的语法,但它也非常有限,因为它只处理存储在项目所分配的行的零列中的单个QModelIndex 。为了能够存储存储在项目行的非零列中的自定义数据(或修改现有数据),我们首先得到项目的行号:

itemRow=item.row()

知道项目的行号,我们可以使用每列来获取所有项目索引 在“手动”模式下:

indexOfColumn1=model.index(itemRow, 1)
indexOfColumn2=model.index(itemRow, 2)

(其中第二个整数参数,例如12是列号)。

或处于“全自动”模式:

for i in range(model.columnCount()):
    eachColumnIndex=model.index(itemRow, i)

知道项目QModelIndexes我们可以使用它们查询或存储数据,就像我们使用item.setData()方法一样(一种只从/向零列分配/检索数据的方法{{ 1}})。

为了存储和检索每列中的数据 - QModelIndex,我们必须使用QModelIndexmodel.setData(index,value,role)方法(看来我们无法使用model.data(index, role)实例直接......就像这样:

QModelIndex - 这是无效的代码,因为myIndex.setData(value,role)没有QModelIndex方法。

为了检索按.setData()存储的数据,我们使用QModelIndex

model.data(index,role)

对于单个列视图(例如model=view.model() print model.data(index, QtCore.Qt.UserRole+1).toPyObject() ),处理提供的.QListView方法可能就足够了。但对于多列视图(例如QStandardItem,有可能必须访问单个列的QTabLeView

enter image description here

QModelIndexe