【问题标题】:how to delegate on specific postion(row, col) in PyQt QTreeView如何在 PyQt QTreeView 中委托特定位置(行,列)
【发布时间】:2015-06-01 13:15:18
【问题描述】:

我的目的是在树视图列表中显示不同的图标当特定位置(行、列)匹配一个值时。 eg: (row, 2) 是目录或文件,会显示不同的图标。因为这没有在本地文件系统中使用,QDir 或 Qfilesystem 模型不适合这个。

我对 MVC 有一点了解,控制器显示在视图中,将模型制作为数据接口 api。但我不知道如何让它像我期望的那样在特定位置(行,列)上工作。

我曾尝试在 ImageDelegate 中添加参数(例如将图标文件名传递给它),但可能由于其父类不接受更多参数而失败。 希望有人能给我一些启示。

class ImageDelegate(QtGui.QStyledItemDelegate):

    def __init__(self, parent=None):
        QtGui.QStyledItemDelegate.__init__(self, parent)
        #self.icon =icon
    def paint(self, painter, option, index):
        #painter.fillRect(option.rect, QtGui.QColor(191,222,185))
        # path = "path\to\my\image.jpg"
        path = "icon1.png"
        image = QtGui.QImage(str(path))
        pixmap = QtGui.QPixmap.fromImage(image)
        pixmap.scaled(16, 16, QtCore.Qt.KeepAspectRatio)
        painter.drawPixmap(option.rect.x(), option.rect.y(),  pixmap)

我可以在我的视图中使用这个委托。但它会改变特定列中的所有行。

def init_remotetreeview(self):
    self.model = myModel(self.remote_Treeview)

    for therow in range(self.model.rowCount(QModelIndex())) :
        print self.model.data(self.model.index(therow, 2, QtCore.QModelIndex()),Qt.DisplayRole).toString()   # i do check the value will used to load correct icon.
    self.remote_Treeview.setItemDelegate(ImageDelegate(self))  # this change all lines
    self.remote_Treeview.setModel(self.model)

【问题讨论】:

  • 如果我理解正确,您只希望第 4 列中的图标(我假设每行一个图标?)依赖于第 2 列的内容?如果是这种情况,您根本不需要委托。您只需要更改模型的行为方式。你能提供一些代码来显示你的模型的实现吗?

标签: delegates icons pyqt qtreeview


【解决方案1】:

事实上,您的代码中有some light,不是吗? (开个玩笑。)

您有正确的方式使用QtGui.QStyledItemDelegate。我有参考如何实现它(但是,仅限 C++)。 'Star Delegate Example''QItemDelegate Class Reference C++''QItemDelegate Class Reference PyQt4'

关键字:你必须实现paint 绘制你想要的元素(我认为这是你想要的。)

小例子,希望就是帮助;

import sys
from PyQt4 import QtCore, QtGui
from functools import partial

class QCustomDelegate (QtGui.QItemDelegate):
    signalNewPath = QtCore.pyqtSignal(object)

    def createEditor (self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            editorQWidget = QtGui.QPushButton(parentQWidget)
            editorQWidget.released.connect(partial(self.requestNewPath, indexQModelIndex))
            return editorQWidget            
        else:
            return QtGui.QItemDelegate.createEditor(self, parentQWidget, optionQStyleOptionViewItem, indexQModelIndex)

    def setEditorData (self, editorQWidget, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
            editorQWidget.setText(textQString)
        else:
            QtGui.QItemDelegate.setEditorData(self, editorQWidget, indexQModelIndex)

    def setModelData (self, editorQWidget, modelQAbstractItemModel, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            textQString = editorQWidget.text()
            modelQAbstractItemModel.setData(indexQModelIndex, textQString, QtCore.Qt.EditRole)
        else:
            QtGui.QItemDelegate.setModelData(self, editorQWidget, modelQAbstractItemModel, indexQModelIndex)

    def updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            editorQWidget.setGeometry(optionQStyleOptionViewItem.rect)
        else:
            QtGui.QItemDelegate.updateEditorGeometry(self, editorQWidget, optionQStyleOptionViewItem, indexQModelIndex)

    def requestNewPath (self, indexQModelIndex):
        self.signalNewPath.emit(indexQModelIndex)

    def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 0:
            textQString = indexQModelIndex.model().data(indexQModelIndex, QtCore.Qt.EditRole).toString()
            painterQPainter.drawPixmap (
                optionQStyleOptionViewItem.rect.x(),
                optionQStyleOptionViewItem.rect.y(),
                QtGui.QPixmap(textQString).scaled(180, 180, QtCore.Qt.KeepAspectRatio))
        else:
            QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)

class QCustomTreeWidget (QtGui.QTreeWidget):
    def __init__(self, parent = None):
        super(QCustomTreeWidget, self).__init__(parent)
        self.setColumnCount(1)
        myQCustomDelegate = QCustomDelegate()
        self.setItemDelegate(myQCustomDelegate)
        myQCustomDelegate.signalNewPath.connect(self.getNewPath)

    def addMenu (self, path, parentQTreeWidgetItem = None):
        if parentQTreeWidgetItem == None:
            parentQTreeWidgetItem = self.invisibleRootItem()
        currentQTreeWidgetItem = QtGui.QTreeWidgetItem(parentQTreeWidgetItem)
        currentQTreeWidgetItem.setData(0, QtCore.Qt.EditRole, path)
        currentQTreeWidgetItem.setFlags(currentQTreeWidgetItem.flags() | QtCore.Qt.ItemIsEditable)
        for i in range(self.columnCount()):
            currentQSize = currentQTreeWidgetItem.sizeHint(i)
            currentQTreeWidgetItem.setSizeHint(i, QtCore.QSize(currentQSize.width(), currentQSize.height() + 200))

    def getNewPath (self, indexQModelIndex):
        currentQTreeWidgetItem = self.itemFromIndex(indexQModelIndex)
        pathQStringList = QtGui.QFileDialog.getOpenFileNames()
        if pathQStringList.count() > 0:
            textQString = pathQStringList.first()
            currentQTreeWidgetItem.setData(indexQModelIndex.column(), QtCore.Qt.EditRole, textQString)
            print textQString

class QCustomQWidget (QtGui.QWidget):
    def __init__ (self, parent = None):
        super(QCustomQWidget, self).__init__(parent)
        self.myQCustomTreeWidget = QCustomTreeWidget(self)
        self.allQHBoxLayout = QtGui.QHBoxLayout()
        self.allQHBoxLayout.addWidget(self.myQCustomTreeWidget)
        self.setLayout(self.allQHBoxLayout)
        self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter01.jpg''')
        self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter02.jpg''')
        self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter04.jpg''')
        self.myQCustomTreeWidget.addMenu(r'''C:\Users\Kitsune Meyoko\Desktop\twitter05.jpg''')

app = QtGui.QApplication([])
myQCustomQWidget = QCustomQWidget()
myQCustomQWidget.show()
sys.exit(app.exec_())

注意:QTreeView的实现方式相同,只是设置值不同。

如果您想在某个索引中按路径显示图像(在这种情况下:2nd)。你可以使用QModelIndex QAbstractItemModel.index (self, int row, int column, QModelIndex parent = QModelIndex()) 找到它,并且想要你想要的。

示例;

import sys
from PyQt4 import QtCore, QtGui

class QCustomDelegate (QtGui.QItemDelegate):
    def paint (self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex):
        column = indexQModelIndex.column()
        if column == 3:
            currentQAbstractItemModel = indexQModelIndex.model()
            iconQModelIndex           = currentQAbstractItemModel.index(indexQModelIndex.row(), 1, indexQModelIndex.parent())
            pathQString               = currentQAbstractItemModel.data(iconQModelIndex, QtCore.Qt.EditRole).toString()
            iconQPixmap               = QtGui.QPixmap(pathQString)
            if not iconQPixmap.isNull():
                painterQPainter.drawPixmap (
                    optionQStyleOptionViewItem.rect.x(),
                    optionQStyleOptionViewItem.rect.y(),
                    iconQPixmap.scaled(20, 20, QtCore.Qt.KeepAspectRatio))
        else:
            QtGui.QItemDelegate.paint(self, painterQPainter, optionQStyleOptionViewItem, indexQModelIndex)

myQApplication = QtGui.QApplication([])

myQTreeView = QtGui.QTreeView()
headerQStandardItemModel = QtGui.QStandardItemModel()
headerQStandardItemModel.setHorizontalHeaderLabels([''] * 4)
myQTreeView.setModel(headerQStandardItemModel)
# Set delegate
myQCustomDelegate = QCustomDelegate()
myQTreeView.setItemDelegate(myQCustomDelegate)
# Append data row 1
row1QStandardItem = QtGui.QStandardItem('ROW 1')
row1QStandardItem.appendRow([QtGui.QStandardItem(''), QtGui.QStandardItem('1.jpg'), QtGui.QStandardItem(''), QtGui.QStandardItem('')])
headerQStandardItemModel.appendRow(row1QStandardItem)
# Append data row 2
row2QStandardItem = QtGui.QStandardItem('ROW 2')
row2QStandardItem.appendRow([QtGui.QStandardItem(''), QtGui.QStandardItem('2.png'), QtGui.QStandardItem(''), QtGui.QStandardItem('')])
headerQStandardItemModel.appendRow(row2QStandardItem)
myQTreeView.show()
sys.exit(myQApplication.exec_())

实验结果:

注意:我有图片 1.jpg、2.png。

【讨论】:

  • 是的,我知道如何使用基本的 setDelegateForColumn,我的问题是我在 TreeView 中有 4 列显示,第 4 列显示图标,但实际上我需要在第 2 列显示不同的基本图标价值。 treewidget 放图标可能有点容易,我卡在 TreeView 上
  • 好的,很抱歉弄错了你的问题。请阅读我的最后一个答案。
  • 谢谢,QstandarditemModel,应该是简单而正确的方式来做到这一点。感谢您的样品。
猜你喜欢
  • 2016-04-09
  • 2017-04-23
  • 2015-11-20
  • 2023-04-03
  • 2014-06-12
  • 1970-01-01
  • 2018-05-30
  • 2011-05-23
  • 2017-06-26
相关资源
最近更新 更多