下面的代码创建了一个包含三个项目的QListView。此QListView通过其.model填充。如果不使用模型,我可以继续做这样的事情:
view=QtGui.QListWidget()
item=QtGui.QListWidgetItem()
item.setText('Item Name')
icon=QtGui.QIcon('/Volumes/path/to/file.jpg')
item.setIcon(icon)
view.addItem(item)
但是使用`.model'时没有可用的项目(而是使用索引)。请指教。
import os,sys
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 Model(QtCore.QAbstractListModel):
def __init__(self):
QtCore.QAbstractListModel.__init__(self)
self.items=[]
self.modelDict={}
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()]
def addItems(self):
for key in self.modelDict:
index=QtCore.QModelIndex()
self.beginInsertRows(index, 0, 0)
self.items.append(key)
self.endInsertRows()
class ListView(QtGui.QListView):
def __init__(self):
super(ListView, self).__init__()
self.model= Model()
self.model.modelDict=elements
self.model.addItems()
self.setModel(self.model)
self.show()
window=ListView()
sys.exit(app.exec_())
以下代码修订了之前发布的完整工作版本。基本上我们必须提供所需数据的模型。实际图标“赋值”将由模型本身处理。我们只需要确保图标请求发生在正确的if Role==x
范围内。应在if DecorationRole
方法的.data()
部分中请求/返回图标。还有其他角色:Qt.DisplayRole, Qt.TextAlignmentRole, Qt.TextColorRole, Qt.BackgroundColorRole, Qt.ItemDataRole, Qt.UserRole
等等)
import os,sys
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'}}
icon=QtGui.QIcon('C:\\myIcon.png')
class Model(QtCore.QAbstractListModel):
def __init__(self):
QtCore.QAbstractListModel.__init__(self)
self.items=[]
self.modelDict={}
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.DecorationRole:
return icon
def addItems(self):
for key in self.modelDict:
index=QtCore.QModelIndex()
self.beginInsertRows(index, 0, 0)
self.items.append(key)
self.endInsertRows()
class ListView(QtGui.QListView):
def __init__(self):
super(ListView, self).__init__()
self.model= Model()
self.model.modelDict=elements
self.model.addItems()
self.setModel(self.model)
self.show()
window=ListView()
sys.exit(app.exec_())
答案 0 :(得分:3)
首先,当传入的角色为DecorationRole
时,您需要Model.data
才能返回QIcon
(或QPixmap
,如果更方便的话) 。使用这个当前代码,它将返回None
,它不仅没有做你想要的,实际上是无效的。如果它不知道如何处理传递的角色,它应该返回一个无效的QVariant
(就像你在方法的第一行所做的那样)。 PyQt可能足够聪明,可以正确处理None
。
其次,您似乎已正确使用QModelIndex
。您可以将图标设置为与您访问的模型本身相关联的另一个字段。 QListWidgetItem
只是一个便利类,没有什么可以阻止你封装与你在模型上存储的类似类中的行相关的所有数据(就像你已经使用DisplayRole
一样数据)并通过QModelIndex.row()
进行访问。
这样的事情:
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()]
if role == QtCore.Qt.DecorationRole:
return self.icons[index.row()]
return QtCore.QVariant()
虽然我个人建议使用一个dict,其值包含DisplayRole
和DecorationRole
数据作为类中的字段。
如果QListView
默认情况下会从模型中请求DecorationRole
,我不知道副作用。您可能需要在列表视图中设置iconSize
属性或类似属性。这些都是您需要对模型本身进行的所有更改。