下面的代码创建了一个“附加”了数据和代理模型的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')
设置的字符串“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_())
最佳答案
这是一个关于如何使用 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
要创建一个 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 因为 TableView 中有列。所以不需要创建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)
上面的所有三个赋值行都用于为同一个“项目”分配三个不同的值:第一个值是一个字符串 '< 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)
(其中第二个整数参数,例如 1
或 2
是列号)。
或者在“全自动”模式下:
for i in range(model.columnCount()):
eachColumnIndex=model.index(itemRow, i)
了解项目的 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()
对于单列 View (例如 .QListView
)处理提供的 QStandardItem
方法可能就足够了。但是对于多列 View (例如 QTabLeView
,有可能必须访问单个列的 QModelIndexe
。
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_())
关于python - 如何访问存储在 QModelIndex 中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25943153/