【问题标题】:Styling the items of a QComboBox menu individually PyQt5单独设置 QComboBox 菜单项的样式 PyQt5
【发布时间】:2020-08-02 13:56:04
【问题描述】:

我试图单独设置 QComboBox 菜单项的样式。 在Qt Style Sheets Examples 中,它通过 QAbstractItemView

设置菜单样式
QComboBox QAbstractItemView {
    border: 2px solid darkgray;
    selection-background-color: lightgray;
}

它提供了对菜单的一般控制,但对单个项目没有控制,除了对所选项目的轻微控制。另一种解决方案是使用对我不起作用的 QAbstractItemView::item

【问题讨论】:

    标签: python pyqt qcombobox


    【解决方案1】:

    您似乎有一个XY problem,因为正如您指出的那样,您的目标是“绘制下拉菜单”(这是非常通用的),但您要求可能的解决方案(另一个问题)的错误不会一定要为你服务。

    考虑到以上,我会解释错误的原因和可能的解决方案(显然做了很多假设)。

    主要错误是这段代码是针对 PyQt4 的,您可能正在使用 PyQt5,在 PyQt4 中,data() 方法返回一个必须转换为 python 对象的 QVariant,因此您使用 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)
    

    更新:

    通过修改问题,可以验证 OP 存在 XY 问题。要修改 QComboBox 的项目的绘制,必须使用委托:QItemDelegate 或 QStyledItemDelegate。我更喜欢使用第二种,因为它使用的是QStyle,即设计会尊重GUI的风格。要设置每个项目的颜色,请使用 QStyleOptionViewItem 的 backgroundBrush 属性,并且对于边框绘制,则必须重写 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_())
    

    【讨论】:

    • @O.Shehab 如果您希望它是文本,那么您不需要使用委托(删除self.delegate = LineStyleDelegate(self.searchEdit)self.searchEdit.setItemDelegate(self.delegate))。正如我指出的那样,您的问题令人困惑,请更好地解释自己。请记住,SO 不是教程服务。
    • 我想更好地控制组合框项目的样式,而我找到的唯一答案就是绘制它。
    • @O.Shehab Pointing 我想更好地控制组合框项目的样式非常通用,如果您的要求具体,我们可以为您提供帮助。在 Qt 中有很多方法可以设置元素的样式。
    • 我知道如何在 PyQt 中设置元素的样式,但我花了两个小时或更长时间试图找到一种方法来通过样式设置 QAbstractItemView 来设置组合框项的样式,但它们都不起作用。
    • @O.Shehab 正如我已经指出的那样:如果您的要求不具体,那么我将无法为您提供帮助,再见。
    猜你喜欢
    • 2012-08-31
    • 2023-03-17
    • 2018-12-10
    • 2019-08-24
    • 2013-10-05
    • 1970-01-01
    • 2020-06-06
    • 2022-01-21
    • 1970-01-01
    相关资源
    最近更新 更多