如何在PyQt QTreeView中委托特定的位置(row,col)

时间:2014-09-01 15:44:49

标签: delegates icons pyqt qtreeview

我的目的是在特定位置(行,列)与值匹配时,在树视图列表显示不同的图标。例如:(row,2)是dir或file,将显示不同的图标。因为这不用于本地文件系统,QDir或Qfilesystem模型不适用于此。

我知道MVC中有一点控制器在视图中显示,使模型成为数据接口api。但我不知道如何使它适用于我所期望的特定位置(行,col)。

我试图在ImageDelegate中添加args(就像传递图标文件名一样),但失败可能是因为它的父类不接受更多的args。 希望有人能给我一些启示。

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)

1 个答案:

答案 0 :(得分:2)

事实上,您的代码中有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,但只有设置值不同。

如果您想在某个索引中按路径显示图像(在本例中为第2个)。你可以使用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。