【问题标题】:How to assign thumb or icon to QListView Item while using .model使用 .model 时如何将拇指或图标分配给 QListView 项
【发布时间】:2014-09-17 11:47:35
【问题描述】:

下面的代码创建了一个包含三个项目的 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_())

编辑:感谢 Jeffrey 的详细解释!


下面的代码是之前发布的代码的完整修改版本。基本上我们必须为模型提供所请求的数据。实际的图标“分配”将由模型本身处理。我们只需要确保图标请求发生在正确的if Role==x 范围内。图标应在.data() 方法的if DecorationRole 部分中请求/返回。还有其他可用的角色: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_()) 

【问题讨论】:

    标签: python qt pyqt


    【解决方案1】:

    首先,当传入的角色为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,其值包含 DisplayRoleDecorationRole 数据作为类的字段。

    我不知道QListView 是否会默认向模型请求DecorationRole。您可能需要在列表视图上设置iconSize 属性,或类似的。不过,这些都是您需要对模型本身进行的所有更改。

    【讨论】:

    • 感谢您的解释!我仍然不明白index 对图标的分配是如何以及在哪里发生的......在.addItem() 方法中?
    • 如何使用index (QModelIndex) 而不是“常规”QListWidgetItem 分配图标?什么是正确的语法?
    • 您没有分配图标。 QListView 从模型中查询它。您目前正在通过为您的子类提供一个字符串列表来构建一个模型。你也可以给它一个对应的图标列表,或者有一个像这样的列表:elements = [ {'icon': QIcon(), 'name': 'name' }, ... ] 并在模型的项目中使用它,访问 .icon 或 .name。
    • 所以我总是查询 QModelIndex 只是为了获取它的 .row() 数字,因此它可以用于从类 list 变量中获取“真实”值,例如 elements 或 @987654350 @?对吗?
    • 因此,如果对 self.icons[index.row()] 的请求返回图像的有效文件路径(例如 .png 或 .jpg)model 将注意并将图像分配给相应的 QModelIndex(我意思是QListView Item)?
    猜你喜欢
    • 2012-09-01
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    相关资源
    最近更新 更多