PyQt Different colors in a single row in a combobox

前端 未结 1 1285
闹比i
闹比i 2021-01-14 10:27

I\'m developing a UI using PyQt where a single item in my Qcombobox can have two or three words separated by commas. So for eg item 1 can be \'Text1, Text2, Text3\'

相关标签:
1条回答
  • 2021-01-14 10:57

    One way to do this is to use a QTextDocument to render rich-text for combobox items (via a custom delegate), and also to convert the rich-text back to plain-text for the current text of the combo-box (via its paint event).

    This would allow you to use html for the item text, like so:

        self.combo = RichTextCombo(self)
        self.combo.addItem("""
            <span style="background-color: blue">Blue</span>
            <span style="background-color: red">Red</span>
            """)
    

    Here's the combobox class:

    class RichTextCombo(QtGui.QComboBox):
        def __init__(self, *args, **kwargs):
            super(RichTextCombo, self).__init__(*args, **kwargs)
            self._document = QtGui.QTextDocument(self)
            self._delegate = RichTextDelegate(self)
            self.setItemDelegate(self._delegate)
            self.setSizeAdjustPolicy(
                QtGui.QComboBox.AdjustToMinimumContentsLength)
    
        def paintEvent(self, event):
            painter = QtGui.QStylePainter(self)
            painter.setPen(self.palette().color(QtGui.QPalette.Text))
            options = QtGui.QStyleOptionComboBox()
            self.initStyleOption(options)
            self._document.setHtml(options.currentText)
            options.currentText = self._document.toPlainText()
            painter.drawComplexControl(QtGui.QStyle.CC_ComboBox, options)
            painter.drawControl(QtGui.QStyle.CE_ComboBoxLabel, options)
    

    and here's the custom item-delegate:

    class RichTextDelegate(QtGui.QStyledItemDelegate):
        def __init__(self, *args, **kwargs):
            super(RichTextDelegate, self).__init__(*args, **kwargs)
            self._document = QtGui.QTextDocument(self)
    
        def paint(self, painter, option, index):
            options = QtGui.QStyleOptionViewItemV4(option)
            self.initStyleOption(options, index)
            if options.widget is not None:
                style = options.widget.style()
            else:
                style = QtGui.QApplication.style()
            self._document.setHtml(options.text)
            options.text = ''
            style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter)
            context = QtGui.QAbstractTextDocumentLayout.PaintContext()
            if options.state & QtGui.QStyle.State_Selected:
                context.palette.setColor(
                    QtGui.QPalette.Text, options.palette.color(
                        QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))
            textRect = style.subElementRect(
                QtGui.QStyle.SE_ItemViewItemText, options)
            painter.save()
            painter.translate(textRect.topLeft())
            painter.setClipRect(textRect.translated(-textRect.topLeft()))
            self._document.documentLayout().draw(painter, context)
            painter.restore()
    
        def sizeHint(self, option, index):
            options = QtGui.QStyleOptionViewItemV4(option)
            self.initStyleOption(options,index)
            self._document.setHtml(options.text)
            self._document.setTextWidth(options.rect.width())
            return QtCore.QSize(self._document.idealWidth(),
                                self._document.size().height())
    
    0 讨论(0)
提交回复
热议问题