QIcon的PyQt5 "Ghost"出现在QComboBox的QLineEdit中

PyQt5 "Ghost" of QIcon appears in QLineEdit of a QComboBox

我有一个 QComboBox,我希望每个项目都有自己的 QIcon,但 QIcon 应该只在下拉列表中可见。我从 那里得到了答案并且效果很好:

如您所见,图标仅出现在下拉列表中。当我将 QComboBox 设置为可编辑时出现了问题,并且发生了这种情况:

这里 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()

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)
        <b>self._style = ProxyStyle(self.style())
        self.setStyle(self._style)</b>
        self.editable_index = 99
        self.currentIndexChanged.connect(self.set_editable)
        # ...