Я хочу создать собственный виджет ListView, в котором есть такие настраиваемые элементы: https://i.stack.imgur.com/iTNbN.png

Однако в документации по qt и в некоторых сообщениях о stackoverflow указано, что в идеале следует использовать QStyleItemDelegate. Я никогда раньше не работал с «делегатами», но насколько я понял из моего исследования, они вызываются ListView для рисования / рендеринга каждого элемента.

Я нашел пример делегата в другом проекте (https: // github .com / pyblish / pyblish-lite / blob / master / pyblish_lite / delegate.py), и они рисуют все вручную / по сути перестраивают целые виджеты, раскрашивая прямоугольники.

Мне это кажется немного непрактичным, поскольку в большинстве случаев пользовательские виджеты элементов могут быть составными частями существующих виджетов. Взгляните на скриншот выше. По сути, он содержит Qlabel, QPixmap и четыре DoubleSpinBox.

Вопрос: как бы вы использовали методы рисования / визуализации, которые уже существуют в них, вместо того, чтобы вручную рисовать все самостоятельно? Таким образом, вы можете использовать существующие методы членов и использовать макеты для структурирования своего виджета.

Например, первый ListViewItem должен передать данные модели делегату, чтобы текст self.lightGroupName QLabel мог быть установлен на «Light1».

Любая помощь приветствуется, так как я понятия не имею, что делать дальше:

from PySide2 import QtCore, QtGui, QtWidgets

class LightDelagate(QtWidgets.QStyledItemDelegate): #custom item view
    def __init__(self, parent=None):
        super(LightDelagate, self).__init__(parent)
        self.setupUI()

    def setupUI(self):
        self.masterWidget = QtWidgets.QWidget()

        #Light Group Header 
        self.hlayLightHeader = QtWidgets.QHBoxLayout()
        self.lightGroupName = QtWidgets.QLabel("Checker")
        self.hlayLightHeader.addWidget(self.lightGroupName)

        #Light AOV Preview
        self.lightPreview = QtWidgets.QLabel()
        #set size 
        self.aovThumbnail = QtGui.QPixmap(180, 101)
        #self.lightPreview.setPixmap(self.aovThumbnail.scaled(self.lightPreview.width(), self.lightPreview.height(), QtCore.Qt.KeepAspectRatio))

        # #Color Dials
        # self.hlayColorDials = QtWidgets.QHBoxLayout()
        # self.rgbDials = QtWidgets.QHBoxLayout()
        # self.rDial = QtWidgets.QDoubleSpinBox()
        # self.rDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
        # self.gDial = QtWidgets.QDoubleSpinBox()
        # self.gDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
        # self.bDial = QtWidgets.QDoubleSpinBox()
        # self.bDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
        # self.rgbDials.addWidget(self.rDial)
        # self.rgbDials.addWidget(self.gDial)
        # self.rgbDials.addWidget(self.bDial)
        # #Exposure
        # self.hlayExposureDials = QtWidgets.QHBoxLayout()
        # self.exposureDial = QtWidgets.QDoubleSpinBox()
        # self.exposureDial.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)

        # self.hlayExposureDials.addWidget(self.exposureDial)
        # self.hlayColorDials.addLayout(self.rgbDials)
        # self.hlayColorDials.addLayout(self.hlayExposureDials)

        #entire layout
        self.vlayWidget = QtWidgets.QVBoxLayout()
        self.vlayWidget.addLayout(self.hlayLightHeader)
        self.vlayWidget.addWidget(self.lightPreview)
        # self.vlayWidget.addLayout(self.hlayColorDials)
        self.vlayWidget.setContentsMargins(2,2,2,2)
        self.vlayWidget.setSpacing(2)
        self.masterWidget.setLayout(self.vlayWidget)



    def paint(self, painter, option, index):
        rowData = index.model().data(index, QtCore.Qt.DisplayRole)
        self.lightGroupName.setText(rowData[0])
        print (option.rect)
        painter.drawRect(option.rect)
        painter.drawText()
    def sizeHint(self, option, index):
        return QtCore.QSize(200, 150)

class LightListModel(QtCore.QAbstractListModel): #data container for list view
    def __init__(self, lightList= None):
        super(LightListModel, self).__init__()
        self.lightList = lightList or []

    #reimplement
    def rowCount(self, index):
        return len(self.lightList)

    def data(self, index, role):
        if role == QtCore.Qt.DisplayRole:
            lightGroupData = self.lightList[index.row()]
            return lightGroupData


class LightListView(QtWidgets.QListView): #
    def __init__(self):
        super(LightListView, self).__init__()
        self.setFlow(QtWidgets.QListView.LeftToRight)
        self.setItemDelegate(LightDelagate(self))
        self.setMinimumWidth(1880)

lightListTest = [ 
    ('Light1' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)}),
    ('Light2' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)}),
    ('Light3' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)}),
    ('Light4' , {'lightList' : [], 'lightColor': (0,0,0), 'mod_exposure': 1, 'mod_color' : (0,0,0)})
]

app = QtWidgets.QApplication([])
LLV = LightListView()
model = LightListModel(lightList=lightListTest)
LLV.setModel(model)
LLV.show()
LLV.setSe
app.exec_()
1
ChemicalMoss 23 Окт 2019 в 22:57

1 ответ

Не могли бы вы вместо QListView использовать QListWidget и переопределить itemWidget? Идея заключалась бы в том, что это позволит вам вернуть QWidget (с дочерними элементами, как показано на вашем снимке экрана) вместо того, чтобы реализовывать QStyledItemDelegate, который вызывает метод каждого дочернего виджета paint.

0
Michael Herrmann 24 Окт 2019 в 08:34
Нет, к сожалению .setItemWidget () и QListWidget не подходят, так как я должен использовать структуру модель / представление.
 – 
ChemicalMoss
24 Окт 2019 в 12:12