Используйте QItemDelegate, чтобы нарисовать иконку - PullRequest
0 голосов
/ 11 января 2019

Я хочу нарисовать второй значок в одном столбце справа от стандартного события рисования этого столбца. Как вы можете видеть ниже, я рисую красный значок в правой части элементов в столбце 3. Как мне поступить, используя QItemDelegate? Я бы предпочел, чтобы рисование по умолчанию даже продолжалось, чтобы испортить роль украшения и отобразить текст роли.

enter image description here

import os, sys, pprint
from Qt import QtGui, QtWidgets, QtCore


class Window(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.resize(500, 400)

        self.uiItems = QtWidgets.QTreeView()
        self.uiItems.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.uiItems.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.uiItems.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.uiItems.setModel(QtGui.QStandardItemModel())
        self.uiItems.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.uiItems)
        self.setLayout(self.layout)

        for i in range(3):
            parent1 = QtGui.QStandardItem('Parente Item ' + str(i))
            parent2 = QtGui.QStandardItem()
            parent3 = QtGui.QStandardItem()
            self.uiItems.model().appendRow([parent1, parent2, parent3])

            for x in range(3):
                col1 = QtGui.QStandardItem('Child Item' + str(x))
                col2 = QtGui.QStandardItem('Item' + str(x))
                col3 = QtGui.QStandardItem('Item' + str(x))
                col3.setData(self.createDotPixmap(), role=QtCore.Qt.DecorationRole)
                parent1.appendRow([col1,col2,col3])

        self.uiItems.expandAll()


    def createRectPixmap(self, col=QtGui.QColor(240,50,50)):
        px = QtGui.QPixmap(12,12)
        px.fill(QtCore.Qt.transparent)
        pxSize = px.rect().adjusted(1,1,-1,-1)
        painter = QtGui.QPainter(px)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setBrush(col)
        painter.setPen(QtGui.QPen(QtGui.QColor(150,20,20), 1.25))
        painter.drawRect(pxSize)
        painter.end()
        return px


    def createDotPixmap(self, col=QtGui.QColor(128,128,128)):
        px = QtGui.QPixmap(12,12)
        px.fill(QtCore.Qt.transparent)
        pxSize = px.rect().adjusted(1,1,-1,-1)
        painter = QtGui.QPainter(px)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setBrush(col)
        painter.setPen(QtGui.QPen(QtGui.QColor(15,15,15), 1.25))
        painter.drawEllipse(pxSize)
        painter.end()
        return px




if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = Window()
    ex.show()
    app.exec_()

1 Ответ

0 голосов
/ 11 января 2019

Решение:

import os, sys, pprint
from Qt import QtGui, QtWidgets, QtCore

DecorationRole2 = QtCore.Qt.UserRole + 1000

class IconDelegate(QtWidgets.QStyledItemDelegate):
    def paint(self, painter, option, index):
        super(self.__class__, self).paint(painter, option, index)
        value = index.data(DecorationRole2)
        if value:
            margin = 10
            mode = QtGui.QIcon.Normal

            if not (option.state & QtWidgets.QStyle.State_Enabled):
                mode = QtGui.QIcon.Disabled
            elif option.state & QtWidgets.QStyle.State_Selected:
                mode = QtGui.QIcon.Selected

            if isinstance(value, QtGui.QPixmap):
                icon = QtGui.QIcon(value)
                option.decorationSize = value.size() / value.devicePixelRatio()

            elif isinstance(value, QtGui.QColor):
                pixmap = QtGui.QPixmap(option.decorationSize)
                pixmap.fill(value)
                icon = QtGui.QIcon(pixmap)

            elif isinstance(value, QtGui.Image):
                icon = QtGui.QIcon(QtGui.QPixmap.fromImage(value))
                option.decorationSize = value.size() / value.devicePixelRatio()

            elif isinstance(value, QtGui.QIcon):
                state =  QtGui.QIcon.On if option.state & QtWidgets.QStyle.State_Open else QtGui.QIcon.Off
                actualSize = option.icon.actualSize(option.decorationSize, mode, state)
                option.decorationSize = QtCore.QSize(min(option.decorationSize.width(), actualSize.width()), min(option.decorationSize.height(), actualSize.height()))

            r = QtCore.QRect(QtCore.QPoint(), option.decorationSize)
            r.moveCenter(option.rect.center())
            r.setRight(option.rect.right() - margin)
            state = QtGui.QIcon.On if option.state & QtWidgets.QStyle.State_Open else QtGui.QIcon.Off
            icon.paint(painter, r, QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter, mode, state)

class Window(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.resize(500, 400)

        self.uiItems = QtWidgets.QTreeView()
        self.uiItems.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.uiItems.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.uiItems.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
        self.uiItems.setModel(QtGui.QStandardItemModel())
        self.uiItems.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)

        delegate = IconDelegate(self.uiItems)
        self.uiItems.setItemDelegateForColumn(2, delegate)

        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.uiItems)
        self.setLayout(self.layout)

        for i in range(3):
            parent1 = QtGui.QStandardItem('Parente Item ' + str(i))
            parent2 = QtGui.QStandardItem()
            parent3 = QtGui.QStandardItem()
            self.uiItems.model().appendRow([parent1, parent2, parent3])

            for x in range(3):
                col1 = QtGui.QStandardItem('Child Item' + str(x))
                col2 = QtGui.QStandardItem('Item' + str(x))
                col3 = QtGui.QStandardItem('Item' + str(x))
                col3.setData(self.createDotPixmap(), role=QtCore.Qt.DecorationRole)
                col3.setData(self.createRectPixmap(), role=DecorationRole2)
                parent1.appendRow([col1,col2,col3])
        self.uiItems.expandAll()

    def createRectPixmap(self, col=QtGui.QColor(240,50,50)):
        px = QtGui.QPixmap(12,12)
        px.fill(QtCore.Qt.transparent)
        pxSize = px.rect().adjusted(1,1,-1,-1)
        painter = QtGui.QPainter(px)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setBrush(col)
        painter.setPen(QtGui.QPen(QtGui.QColor(150,20,20), 1.25))
        painter.drawRect(pxSize)
        painter.end()
        return px


    def createDotPixmap(self, col=QtGui.QColor(128,128,128)):
        px = QtGui.QPixmap(12,12)
        px.fill(QtCore.Qt.transparent)
        pxSize = px.rect().adjusted(1,1,-1,-1)
        painter = QtGui.QPainter(px)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)
        painter.setBrush(col)
        painter.setPen(QtGui.QPen(QtGui.QColor(15,15,15), 1.25))
        painter.drawEllipse(pxSize)
        painter.end()
        return px

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    ex = Window()
    ex.show()
    app.exec_()
...