下面的代码创建了一个单独QListView的数据和代理模型"附加".单击其中一个单选按钮可调用buttonClicked()功能.
此函数调用模型的.data(index,role)方法来获取存储在当前索引中的数据.
对于DisplayRole模型的.data()方法,正确返回索引的名称(在创建时分配给它).但是当使用
'ItemDataRole'时,我收到一个错误:
TypeError: QSortFilterProxyModel.data(QModelIndex, int role=Qt.DisplayRole): argument 2 has unexpected type 'sip.enumtype'
Run Code Online (Sandbox Code Playgroud)
-
Question 1: How to fix this error?
Run Code Online (Sandbox Code Playgroud)
如果你看看addItems()方法,那里有一条线:
self.setData(index, 'keyword')
Run Code Online (Sandbox Code Playgroud)
显然我正在尝试将'keyword'设置为我自己的"自定义数据"(这是过滤索引时将使用的ProxyModel吗?).
问题2:如何查询我设置的字符串"keyword" self.setData(index, 'keyword')?这些数据是可访问的还是"保留"且无法查询?

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_())
Run Code Online (Sandbox Code Playgroud)
下面是关于如何使用工作示例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
Run Code Online (Sandbox Code Playgroud)
要创建视图项,请先声明它:
item=QtGui.QStandardItem('My Item Name') # stored 'My Item Name' can be queried using `Qt.DisplayRole` flag
Run Code Online (Sandbox Code Playgroud)
QStandardItem使用以下命令分配声明视图:
model.appendRow(item)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
上面的所有三个赋值行都用于为同一个"item"分配三个不同的值:first value是一个'< Column 0 My Display Value as "DisplayRole" >'存储在Qt.DisplayRolerole 下的字符串(使用此角色将其检索回来).
字符串值:'< Column 0 My Custom Value as "UserRole" >'存储在Qt.UserRole.使用此角色将其检索回来.等等.
虽然item.setData(value,role)方法非常有用并且确实使用了简单的语法,但它也非常有限,因为它只处理QModelIndex存储在项目所分配的行的零列中的单个.为了能够存储存储在项目行的非零列中的自定义数据(或修改现有数据),我们首先得到项目的行号:
itemRow=item.row()
Run Code Online (Sandbox Code Playgroud)
知道了项目的行号,我们可以在"手动"模式下使用每列获取所有项目索引:
indexOfColumn1=model.index(itemRow, 1)
indexOfColumn2=model.index(itemRow, 2)
Run Code Online (Sandbox Code Playgroud)
(其中第二个整数参数,例如1或是2列号).
或者采用"全自动"模式:
for i in range(model.columnCount()):
eachColumnIndex=model.index(itemRow, i)
Run Code Online (Sandbox Code Playgroud)
知道项目QModelIndexes我们可以使用它们来查询或存储数据,就像我们使用item.setData()方法一样(一种只从/向零列分配/转发数据的方法QModelIndex).
为了存储和检索每列中的数据 - QModelIndex我们必须使用model.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()
Run Code Online (Sandbox Code Playgroud)
对于单个列视图(例如.QListView)处理提供的QStandardItem方法可能就足够了.但对于多列视图(例如,QTabLeView有可能QModelIndexe必须访问单个列的s.

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_())
Run Code Online (Sandbox Code Playgroud)