У меня есть QComboBox, и я хочу, чтобы каждый элемент имел свой собственный QIcon, но QIcon должен быть виден только в раскрывающемся списке. Я взял ответ из предыдущего вопроса, и он работает очень хорошо:

enter image description here

Как видите, значок появляется только в раскрывающемся списке. Проблема возникает, когда я устанавливаю для QComboBox возможность редактирования, и происходит следующее:

enter image description here

Здесь все еще присутствует «призрак» QIcon, который, в свою очередь, вытесняет текст. У меня вопрос: что вызывает это и как мне удалить это «призрак», чтобы текст отображался нормально?

Мой код:

from PyQt5.QtWidgets import (
    QApplication,
    QComboBox,
    QHBoxLayout,
    QStyle,
    QStyleOptionComboBox,
    QStylePainter,
    QWidget,
)
from PyQt5.QtGui import QIcon, QPalette
from PyQt5.QtCore import QSize


class EditCombo(QComboBox):
    def __init__(self, parent=None):
        super(EditCombo, self).__init__(parent)
        self.editable_index = 99
        self.currentIndexChanged.connect(self.set_editable)

    def setEditableAfterIndex(self, index):
        self.editable_index = index

    def set_editable(self, index: int) -> None:
        if index >= self.editable_index:
            self.setEditable(True)
        else:
            self.setEditable(False)
        self.update()

    def paintEvent(self, event):
        painter = QStylePainter(self)
        painter.setPen(self.palette().color(QPalette.Text))

        opt = QStyleOptionComboBox()
        self.initStyleOption(opt)
        opt.currentIcon = QIcon()
        opt.iconSize = QSize()

        painter.drawComplexControl(QStyle.CC_ComboBox, opt)
        painter.drawControl(QStyle.CE_ComboBoxLabel, opt)


class Example(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        hbox = QHBoxLayout()

        edit_ico = QIcon("edit.png")
        empty_ico = QIcon("empty.png")  # For margin

        combo = EditCombo(self)
        combo.setEditableAfterIndex(2)
        combo.addItem(empty_ico, "Foo 1")
        combo.addItem(edit_ico, "Foo 2")
        combo.addItem(edit_ico, "Bar 1")
        combo.addItem(edit_ico, "Bar 2")

        hbox.addWidget(combo)

        self.setLayout(hbox)

        self.show()


def main():
    import sys

    app = QApplication(sys.argv)
    ex = Example()
    ex.setFixedWidth(300)
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()
0
Secozzi 23 Янв 2021 в 18:28

1 ответ

Лучший ответ

QComboBox также использует значок для установки положения QLineEdit, который используется, когда QComboBox доступен для редактирования, поэтому вы видите это смещение, если вы не хотите его наблюдать, тогда вам нужно пересчитать геометрию. Следующий код делает это через QProxyStyle:

class ProxyStyle(QProxyStyle):
    def subControlRect(self, control, option, subControl, widget=None):
        r = super().subControlRect(control, option, subControl, widget)
        if control == QStyle.CC_ComboBox and subControl == QStyle.SC_ComboBoxEditField:
            if widget.isEditable():
                widget.lineEdit().setGeometry(r)
        return r
class EditCombo(QComboBox):
    def __init__(self, parent=None):
        super(EditCombo, self).__init__(parent)
        self._style = ProxyStyle(self.style())
        self.setStyle(self._style)
        self.editable_index = 99
        self.currentIndexChanged.connect(self.set_editable)
        # ...
1
eyllanesc 23 Янв 2021 в 16:23