Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    Unsolved QComboBox Custom Paint Event Flickering Issue

    Qt for Python
    1
    3
    139
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Emrecp
      Emrecp last edited by Emrecp

      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!

      1 Reply Last reply Reply Quote 0
      • Emrecp
        Emrecp last edited by Emrecp

        This post is deleted!
        1 Reply Last reply Reply Quote 0
        • Emrecp
          Emrecp last edited by

          Note: PySide6 Version: 6.2.2.1

          1 Reply Last reply Reply Quote 0
          • First post
            Last post