My goal is to create a slow transition animation of QComboBox items when hovering over them - I want it to slowly transition from gray color (QColor(198, 198, 198)
) to white (QColor(255, 255, 255)
) in span of over 300ms, this is how my code looks so far:
from PySide6.QtCore import *
from PySide6.QtWidgets import *
from PySide6.QtGui import *
import sys
class ComboBoxDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
if option.state & QStyle.State_MouseOver: # if hover
background_color = QColor(255, 255, 255)
else: # leaving hover
background_color = QColor(198, 198, 198)
painter.fillRect(option.rect, background_color)
painter.drawText(option.rect, index.data())
class MainWidget(QWidget):
def __init__(self):
super(MainWidget, self).__init__()
self.combo_box = QComboBox(self)
self.combo_box.addItems(['Item 1','Item 2', 'Item 3'])
self.main_layout = QVBoxLayout()
self.main_layout.addWidget(self.combo_box)
self.setLayout(self.main_layout)
delegate = ComboBoxDelegate(self.combo_box)
self.combo_box.setItemDelegate(delegate)
app = QApplication(sys.argv)
window = MainWidget()
window.show()
sys.exit(app.exec())
For now this lets me hover over items in QComboBox and change their background color however without smooth transition I desire.
I've tried using .highlighted.connect()
and grabbing the item with it then tried to animate it via QVariantAnimation
however it doesn't let me animate QStandardItem
with it, then I've tried using QStyledItemDelegate
, and now I am stuck figuring out how can I deploy this transition because I believe it won't be possible to take item from QComboBox as QObject.
You can interpolate QColor
values with QVariantAnimation
and redraw an item of the popup with QAbstractItemView.update()
, like the following example.
...
class ComboBoxDelegate(QStyledItemDelegate):
def __init__(self, combo_box):
super().__init__(combo_box)
self.selected_index = None
self.anim = anim = QVariantAnimation()
anim.setStartValue(QColor(Qt.gray))
anim.setEndValue(QColor(Qt.red))
anim.setDuration(1000)
anim.valueChanged.connect(lambda _:
combo_box.view().update(self.selected_index))
def paint(self, painter, option, index):
anim = self.anim
if option.state & QStyle.State_Selected:
if index != self.selected_index:
self.selected_index = index
anim.stop()
anim.start()
background_color = anim.currentValue()
else:
background_color = anim.startValue()
painter.fillRect(option.rect, background_color)
painter.drawText(option.rect, index.data())
...