QComboBox Custom Paint Event Flickering Issue
Unsolved
Qt for Python
-
Hello,
I am trying to create custom combobox.
Code:# -*- coding: utf-8 -*- import sys, os, time from PySide6 import QtCore, QtWidgets, QtGui from PySide6.QtWidgets import * from PySide6.QtCore import * from PySide6.QtGui import * class EComboBoxData(object): Radius = 15 AnimationTime = 600 # ms FontSize, FontSpacing = 16, 0 Color = { "CORNER": QColor(214, 214, 216), "BASE_BACKGROUND": QColor(247, 247, 250), "BASE_FOREGROUND": QColor(255, 152, 91), "BASE_HOVER_BACKGROUND" :QColor(255, 152, 91), "BASE_HOVER_FOREGROUND": QColor(247, 247, 250), } TextElide = Qt.ElideMiddle class CustomComboDelegate(QStyledItemDelegate): ComboBoxData = EComboBoxData() def __init__(self, ComboBoxData,parent=None): super(CustomComboDelegate, self).__init__(parent) self.ComboBoxData = ComboBoxData self.text_default = self.ComboBoxData.Color["BASE_FOREGROUND"]#QColor(199, 199, 199) self.text_hover = QColor.red#QColor(255, 255, 255) self.cell_default = self.ComboBoxData.Color["BASE_BACKGROUND"]#QColor(67, 67, 67) self.cell_hover = QColor(43, 43, 43) def paint(self, painter, option, index): painter.save() painter.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing) value = index.data(QtCore.Qt.DisplayRole) painter.setFont(self.parent().font()) painter.fillRect(option.rect, self.cell_default) painter.setPen(QPen(self.ComboBoxData.Color["BASE_HOVER_BACKGROUND"],1)) painter.drawText(option.rect, QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter, value) if option.state & QStyle.State_MouseOver: painter.setBrush(self.ComboBoxData.Color["BASE_HOVER_BACKGROUND"]) painter.drawRect(option.rect.adjusted(0,1,0,1)) #painter.drawRoundedRect(option.rect, self.ComboBoxData.Radius, self.ComboBoxData.Radius) painter.setPen(QPen(self.ComboBoxData.Color["BASE_HOVER_FOREGROUND"],1)) painter.drawText(option.rect, QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter, value) painter.restore() class EComboBox(QComboBox): ComboBoxData = EComboBoxData() PrivateData = { "ShowPopup" : False } def __init__(self, ComboBoxData=EComboBoxData()): super(EComboBox, self).__init__(None) self.ComboBoxData = ComboBoxData self.setItemDelegate(CustomComboDelegate(ComboBoxData, self)) self.setMinimumHeight(34) self._animation = QtCore.QPropertyAnimation(self, b"_vallll", duration=self.ComboBoxData.AnimationTime) #id = QFontDatabase.addApplicationFont(r"C:\Users\Emre\Desktop\img\Font\Baloo2-Bold.ttf");id2 = QFontDatabase.addApplicationFont(r"C:\Users\Emre\Desktop\img\Font\Fredoka-Bold.ttf") #fontadi = QFontDatabase.applicationFontFamilies(id);fontadi2 = QFontDatabase.applicationFontFamilies(id2) self.myfont = QFont("Times New Roman", 16, weight=QFont.Bold)#QFont(fontadi[0], 16, weight=QFont.Bold) self.myfont.setWordSpacing(self.ComboBoxData.FontSpacing) self.myfont.setStyleHint(QFont.Monospace) self.myfontMetrics = QFontMetrics(self.myfont) # font.setStyleHint(QFont.Times, QFont.PreferAntialias) self.setFont(self.myfont) self.setMinimumWidth(150) effect = QtWidgets.QGraphicsOpacityEffect(self.model(), opacity=1.0) self.setGraphicsEffect(effect) self._animation = QtCore.QPropertyAnimation( self.model(), propertyName=b"opacity", targetObject=effect, duration=500, startValue=0.0, endValue=1.0, ) self._animation.setDirection(QtCore.QPropertyAnimation.Forward) #self._animation.start() #_vallll = QtCore.Property(int, fget=value, fset=ESetValue, notify=valueChanged) def showPopup(self) -> None: #self.PrivateData["ShowPopup"] = True #self._animation.start() QComboBox.showPopup(self) def hidePopup2(self) -> None: self.PrivateData["ShowPopup"] = False def paintEvent(self, event: QPaintEvent) -> None: pt = QPainter(self) pt.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing ) border = QPainterPath() border.addRoundedRect(QRectF(self.rect().adjusted(2, 2, -3, -3)),self.ComboBoxData.Radius, self.ComboBoxData.Radius) pt.setPen(QPen(self.ComboBoxData.Color['CORNER'], 3.5)) pt.setBrush(self.ComboBoxData.Color['BASE_BACKGROUND']) pt.drawPath(border) pt.setClipPath(border) pen = QPen(QColor(QtCore.Qt.black)) #pen.setWidth(10) brush = QBrush(pen.color().darker(150)) pt.setBrush(brush) w, h = self.width(), self.height() arrow_width, arrow_height = 12, 20 arrow_margin_width, arrow_margin_height = 16, 14 arrowBodyPoints= QPoint() pt.setPen(QPen(self.ComboBoxData.Color['CORNER'], 3)); pt.setBrush(Qt.NoBrush) path2 = QPainterPath() path2.addPolygon(QPolygonF( [QPoint(w-arrow_margin_width-arrow_width, arrow_margin_height),QPoint(w-arrow_margin_width- (arrow_width/2),arrow_height), QPoint(w - arrow_margin_width - (arrow_width / 2),arrow_height), QPoint(w-arrow_margin_width,arrow_margin_height) ])) pt.drawPath(path2) pt.setPen(self.ComboBoxData.Color["BASE_FOREGROUND"]) pt.setFont(self.myfont) TextRect = self.rect().adjusted(4,0, -arrow_width-arrow_margin_width-2,0) Text = self.myfontMetrics.elidedText(self.currentText(), self.ComboBoxData.TextElide, TextRect.width()) pt.drawText(TextRect, Qt.AlignCenter, Text) if __name__ == "__main__": app = QApplication(sys.argv) wind = QMainWindow() wind.setStyleSheet("QMainWindow{background-color:blue}") wind.setWindowTitle("EComboBox") wind.resize(221, 150) wid = QWidget() lay = QHBoxLayout(wid) lay.setAlignment(Qt.AlignCenter) Data = EComboBoxData() e = EComboBox(Data) e.addItems([ "Uzun bir yazı 123","Otomatik", "1 MB/sn", "5 MB/sn", "8 MB/sn"]) lay.addWidget(e) wind.setCentralWidget(wid) wind.show() sys.exit(app.exec())
When click combobox for see items; It flickers.
Video: Flickering
Thanks!