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)
# ...
我有一个 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)
# ...