问题描述
下面的代码创建了一个 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_())
推荐答案
这里是一个关于如何使用 QTableView
和 QStandardItemModel
填充的工作示例QStandardItem
s.
Here is a working example on how to use QTableView
with QStandardItemModel
populated with QStandardItem
s.
使用 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 QModelIndex
es as there are columns in a table-view. So there is no need to create QModelIndex
es 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)
(其中第二个整数参数,例如 1
或 2
是列号).
(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 QModelIndexe
s 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 中的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!