【发布时间】:2021-05-20 09:54:18
【问题描述】:
我想(在这个类比示例中)通过单击 QPushButton 或从代表选择历史的 QComboBox 中选择它来更改 QLabel 的颜色。在实际代码中,控件多于一个按钮,因此有一种方法setColor(self, color) 将新颜色添加到 QComboBox 作为其第一项,删除可能的重复项并更改 QLabel 的颜色。这行得通。
第二个选项是从历史 QComboBox 中选择颜色。当一个项目是pressed 并调用相同的setColor(self, color) 时,我会捕获事件。这会导致问题。
问题是当 QComboBox 中有颜色时,例如['red', 'blue', 'green'] 我选择选项'blue' 并且项目的顺序更改为['blue', 'red', 'green'](我仍然想要这个),有一些标准的QComboBox 行为完成选择并且QComboBox 选择'green' 项目。所以,QLabel 有正确的颜色,但是 QComboBox 没有正确的文本。
如何覆盖“标准行为”并解决此问题?请试试这个例子:
import sys
from random import random
from PyQt5.QtWidgets import QApplication, QWidget, QComboBox, QVBoxLayout, QPushButton, QLabel
class MyCombo(QComboBox):
def __init__(self, parent):
super().__init__(parent)
self.view().pressed.connect(self.handleItemPressed)
def handleItemPressed(self, index):
color = self.model().itemData(index)[0]
self.parent().setColor(color)
def removeDuplicates(self):
unique = list()
while len(unique) < self.model().rowCount():
if self.itemText(len(unique)) in unique:
self.removeItem(len(unique))
else:
unique.append(self.itemText(len(unique)))
class Gui(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.resize(300, 200)
lay = QVBoxLayout()
self.cmb = MyCombo(self)
self.btn = QPushButton('Random', self)
self.btn.clicked.connect(self.btnClicked)
self.pnl = QLabel(self)
lay.addWidget(self.cmb)
lay.addWidget(self.btn)
lay.addWidget(self.pnl)
self.setLayout(lay)
def setColor(self, color):
self.cmb.insertItem(0, color)
self.cmb.setCurrentIndex(0)
self.cmb.removeDuplicates()
self.pnl.setStyleSheet('background-color: %s' % color)
def btnClicked(self):
colors = ['red', 'green', 'blue', 'yellow', 'orange']
self.setColor(colors[int(random() * len(colors))])
if __name__ == '__main__':
app = QApplication(sys.argv)
g = Gui()
g.show()
sys.exit(app.exec_())
【问题讨论】:
-
是否有特定原因使用视图的
pressed信号而不是QComboBox 的currentIndexChanged? -
我想避免循环引用:当我从
btnClicked调用setColor时,索引已更改并触发currentIndexChanged,它再次调用setColor,因为通过选择@ 项目更改了时间987654335@ 被触发并且必须调用setColor来处理所有更改。还是有更好的解决方案?
标签: python-3.x pyqt5 qcombobox