Стилизация элементов меню QComboBox индивидуально PyQt5 - PullRequest
1 голос
/ 20 апреля 2020

Я пытался стилизовать элементы меню QComboBox по отдельности. В примерах таблиц стилей Qt он стилизует меню через QAbstractItemView

QComboBox QAbstractItemView {
    border: 2px solid darkgray;
    selection-background-color: lightgray;
}

, который обеспечивает общий контроль над меню, но не контролирует отдельные элементы, кроме небольшой контроль над выбранным элементом. Другое решение состояло в том, чтобы использовать QAbstractItemView :: item , который не работал для меня.

1 Ответ

1 голос
/ 20 апреля 2020

Кажется, что у вас XY проблема , поскольку, как вы указали, ваша цель - «нарисовать выпадающее меню» (что очень обобщенно c), но вы просите об ошибке возможного решения (другого вопроса), который не обязательно будет вам полезен.

Учитывая вышеизложенное, я объясню причину ошибки и возможное решение (очевидно, сделав много предположений).

Основная ошибка является то, что этот код для PyQt4, и вы, вероятно, используете PyQt5, в PyQt4 метод data () возвращает QVariant, который должен быть преобразован в объект python, поэтому вы используете isValid () и toPyObject (), но в pyqt5 это больше не нужно Другая ошибка заключается в том, что значение UserRole будет None, поскольку вы не указали никакого значения при создании элемента (это может быть вызвано пропуском в другом вопросе).

Учитывая вышеизложенное, возможное решение (совместимо для PyQt4 и PyQt5):

class LineStyleDelegate(QItemDelegate):
    def paint(self, painter, option, index):
        data = index.data(Qt.UserRole)
        if hasattr(data, "toPyObject"):
            data = data.toPyObject()
        if data is not None:
            painter.save()
            rect = option.rect
            rect.adjust(+5, 0, -5, 0)
            pen = QPen()
            pen.setColor(Qt.black)
            pen.setWidth(3)
            pen.setStyle(data)
            painter.setPen(pen)
            middle = (rect.bottom() + rect.top()) / 2
            painter.drawLine(rect.left(), middle, rect.right(), middle)
            painter.restore()
        else:
            QItemDelegate.paint(self, painter, option, index)
        self.searchEdit = QComboBox(sef.searchContent)
        for text, style in (
            ("Item 1", Qt.SolidLine),
            ("Item 2", Qt.DotLine),
            ("Item 3", Qt.DashDotDotLine),
        ):
            self.searchEdit.addItem(text, style)
        self.delegate = LineStyleDelegate(self.searchEdit)
        self.searchEdit.setItemDelegate(self.delegate)
        self.searchEdit.setMinimumWidth(500)
        self.searchEdit.setEditable(True)

ОБНОВЛЕНИЕ:

С изменением вопроса подтверждается, что у ОП была проблема XY. Чтобы изменить рисование элемента QComboBox, необходимо использовать делегат: QItemDelegate или QStyledItemDelegate. Я предпочитаю использовать второй, так как он использует QStyle, то есть дизайн будет соответствовать стилю GUI. Чтобы установить цвет каждого элемента, используйте атрибут backgroundBru sh объекта QStyleOptionViewItem, а для рисования границ необходимо переопределить метод paint ():

import random

from PyQt5 import QtCore, QtGui, QtWidgets


class CustomStyleDelegate(QtWidgets.QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super(CustomStyleDelegate, self).initStyleOption(option, index)
        random_color = QtGui.QColor(*random.sample(range(255), 3))
        option.backgroundBrush = random_color

    def paint(self, painter, option, index):
        super(CustomStyleDelegate, self).paint(painter, option, index)
        margins = 2
        border_color = QtGui.QColor(*random.sample(range(255), 3))
        painter.save()
        pen = QtGui.QPen()
        pen.setColor(border_color)
        pen.setWidth(margins)
        painter.setPen(pen)
        r = QtCore.QRect(option.rect).adjusted(0, 0, -margins, -margins)
        painter.drawRect(r)
        painter.restore()


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = QtWidgets.QComboBox()
    w.addItems(["Item 1", "Item 2", "Item 3"])
    delegate = CustomStyleDelegate(w)
    w.setItemDelegate(delegate)
    w.show()
    sys.exit(app.exec_())
...