本文介绍了如何访问存储在 QModelIndex 中的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码创建了一个 QListView,其中附加"了数据和代理模型.单击其中一个单选按钮会调用 buttonClicked() 函数.

The code below create a single QListView with the data and proxy models "attached".Clicking one of the radio buttons calls for buttonClicked() function.

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

This function calls model's .data(index,role) method to get the data stored in a current index.

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

For the DisplayRole the model's .data() method properly returns the name of index (assigned to it by the time it was created). But when
'ItemDataRole' is used I am getting an error:

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

--

Question 1: How to fix this error?

如果你看看 addItems() 方法,那里有一行:

If you take a look at addItems() method there is a line there:

self.setData(index, 'keyword')

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

Apparently I am trying to set 'keyword' as my own "custom data" (is it what ProxyModel is going to be use while filtering the indexes?).

问题 2:如何查询我用 self.setData(index, 'keyword') 设置的字符串keyword"?这些数据是可访问的还是保留"的,无法查询?

Question 2: How to query the string "keyword" I've set with self.setData(index, 'keyword')?Is this data accessible or it is "reserved" and can't be queried?

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_())

推荐答案

这里是一个关于如何使用 QTableViewQStandardItemModel 填充的工作示例QStandardItems.

Here is a working example on how to use QTableView with QStandardItemModel populated with QStandardItems.

使用 QtGui.QStandardItemModel 优于 QtCore.QAbstractListModel 的一个可能优势是 QtGui.QStandardItemModel 不必被子类化以便分配给 QTableView.您只需继续声明即可:

A possible advantage of using QtGui.QStandardItemModel over QtCore.QAbstractListModel is that QtGui.QStandardItemModel doesn't have to be sub-classed in order to be assigned to QTableView.You just go ahead and declare it:

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

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

To create a view-item declare it first:

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

分配声明的 QStandardItem 以查看使用:

Assign a declared QStandardItem to view using:

model.appendRow(item)

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

model.appendRow(item) method "creates" as many QModelIndexes as there are columns in a table-view. So there is no need to create QModelIndexes manually for each column in a row : the row the item was assigned to.

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

Next using item.setData(value,role) method you can store any type of data using one of pre-defined QModelIndex roles such as:

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)

上述所有三个赋值行都用于为同一个项目"分配三个不同的值:第一个值是一个字符串 '<列 0 My Display Value as "DisplayRole" >' 存储在 Qt.DisplayRole 角色下(使用此角色将其取回).

All three assignment-lines above are used to assign three different values to the same "item": first value is a string '< Column 0 My Display Value as "DisplayRole" >' which is stored under Qt.DisplayRole role (use this role to retrieve it back).

一个字符串值:'<列 0 My Custom Value as "UserRole" >' 存储在 Qt.UserRole 下.使用此角色将其取回.等等

A string value: '< Column 0 My Custom Value as "UserRole" >' is stored under Qt.UserRole. Use this role to retrieve it back. And etc.

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

While item.setData(value,role) method is quite useful and it does use a simple syntax it is also very limited since it only deals with a single QModelIndex stored in a zero column of the row the item is assigned to. In order to be able to store a custom data (or modify an existing data) stored in non-zero columns of the item's row we get the item's row number first:

itemRow=item.row()

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

Knowing the item's row-number we can get all the item indexes from every column usingin a "manual" mode:

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

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

(where a second integer argument such as 1 or 2 are the column numbers).

或者在全自动"模式下:

Or in a "fully automatic" mode:

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

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

Knowing the item's QModelIndexes we can use them to query or store data just like we did using item.setData() method (a method that only assigns/retreives a data from/to a zero-column QModelIndex).

为了存储和检索每列中的数据-QModelIndex 我们必须使用 model.setData(index,value,role)model.data(index, role) 方法(看起来我们不能直接使用 QModelIndex 实例来获取/设置数据......像这样:

In order to store and retreive the data in each-column-QModelIndex we have to use model.setData(index,value,role) and model.data(index, role) methods (it appears we can't get/set the data using QModelIndex instance directly... like this:

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

myIndex.setData(value,role) - this is invalid code since QModelIndex doesn't come with .setData() method.

为了检索每个 QModelIndex 存储的数据,我们使用 model.data(index,role):

In order to retrieve the data stored per QModelIndex we use model.data(index,role):

model=view.model()
print model.data(index, QtCore.Qt.UserRole+1).toPyObject() 

对于处理提供的 QStandardItem 方法的单列视图(例如 .QListView)可能就足够了.但是对于多列视图(例如 QTabLeView,有可能必须访问单个列的 QModelIndexe.

For a single column views (such as .QListView) dealing with supplied QStandardItem methods would be probably sufficient. But for multi-column views (such as QTabLeView there is a chance the individual column's QModelIndexes would have to be accessed.

import os,sys
home=os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
sys.path.append(os.path.join(home,'site-packages'))
from PyQt4 import QtCore, QtGui
app=QtGui.QApplication(sys.argv)
class Window(QtGui.QTableView):
    def __init__(self):
        super(Window, self).__init__() 
        model=QtGui.QStandardItemModel()

        model.setHorizontalHeaderLabels(['Column 0','Column 1','Column 3'])
        for i in range(3):
            item=QtGui.QStandardItem('Column 0 Item %s'%i)
            item.setData('< Column 0 Custom Value as "UserRole" >', QtCore.Qt.UserRole)
            item.setData('< Column 0 Custom Value as "UserRole+1" >', QtCore.Qt.UserRole+1)
            model.appendRow(item)

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

            model.setData(indexOfColumn1, 'Column 1 Item', QtCore.Qt.DisplayRole)
            model.setData(indexOfColumn1, '< Column 1 Custom Value as "UserRole" >', QtCore.Qt.UserRole)

            model.setData(indexOfColumn2, 'Column 2 Item', QtCore.Qt.DisplayRole)
            model.setData(indexOfColumn2, '< Column 2 Custom Value as "UserRole" >', QtCore.Qt.UserRole)

        self.setModel(model)
        self.clicked.connect(self.onClick)  
        self.show()

    def onClick(self,index=None):
        row=index.row()
        column=index.column()

        model=self.model()
        indexOfColumn0=model.index(row, 0)
        indexOfColumn1=model.index(row, 1)
        indexOfColumn2=model.index(row, 2)
        print indexOfColumn0==index, indexOfColumn1==index, indexOfColumn2==index


        print  'ROW: %s  COLUMN: %s'%(row,column)
        print 'DispayRoleData via self.model().data(index,role): "%s"'%self.model().data(index, QtCore.Qt.DisplayRole).toString()
        print 'UserRoleData via self.model().data(index,role): "%s"'%self.model().data(index, QtCore.Qt.UserRole).toPyObject()
        print 'UserRoleData via self.model().data(index,role): "%s"'%self.model().data(index, QtCore.Qt.UserRole+1).toPyObject()      

        for key in self.model().itemData(index):
            print 'self.model.itemData(index):    key: %s  value: %s'%(key, self.model().itemData(index)[key].toString())

        item=self.model().itemFromIndex(index)


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

这篇关于如何访问存储在 QModelIndex 中的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 21:07