Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Custom Button, paintEvent issue
QtWS25 Last Chance

Custom Button, paintEvent issue

Scheduled Pinned Locked Moved Unsolved Qt for Python
pyqt5pyside6custom widgetpainteventbutton
11 Posts 3 Posters 1.1k Views
  • 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.
  • E Offline
    E Offline
    Emrecp
    wrote on 13 Jul 2022, 15:20 last edited by
    #1

    Hello, I am trying to create a animated custom button.
    In this link: Buttons I liked 3 & 19.

    When I try to create it: if you look closely you can see that there is another color in all the corners, i don't know why.
    custom button.png

    My Code:

    AnimateEnabled = True
    def paintEvent(self, event:QPaintEvent):
        ret = None 
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        path = QPainterPath()
        painter.setBrush(QBrush(QColor(255,111,42)))
        painter.setPen(Qt.NoPen)
    
        path.addRoundedRect(QRectF(0,0, self.width(), self.height()), self.ButtonData.Radius, self.ButtonData.Radius) # Base background of button
        painter.drawPath(path) # I need to draw it else color will be changed
    
        if self.AnimateEnabled:
            painter.setBrush(QBrush(QColor(231, 231, 231)))
            path.addRoundedRect(QRectF(0,0, int(self.width()*self.AnimateVal/100.00), self.height()), self.ButtonData.Radius, self.ButtonData.Radius) 
            painter.drawPath(path)
    
        return ret
    

    I would be very grateful if you could help me solve the different color problem in these corners and how I can make the button on the 19th number in this link best way?
    Thanks!

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 13 Jul 2022, 17:35 last edited by
      #2

      Hi,

      Isn't that the color of the first brush you are using ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      E 1 Reply Last reply 13 Jul 2022, 17:40
      0
      • S SGaist
        13 Jul 2022, 17:35

        Hi,

        Isn't that the color of the first brush you are using ?

        E Offline
        E Offline
        Emrecp
        wrote on 13 Jul 2022, 17:40 last edited by
        #3

        @SGaist Yes, but it has to be in the background because new drawing is being made on it (same radius)

        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 13 Jul 2022, 19:41 last edited by
          #4

          Are you sure the actual width is the same ?
          You are doing some maths that may alter that.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          E 1 Reply Last reply 13 Jul 2022, 20:02
          0
          • S SGaist
            13 Jul 2022, 19:41

            Are you sure the actual width is the same ?
            You are doing some maths that may alter that.

            E Offline
            E Offline
            Emrecp
            wrote on 13 Jul 2022, 20:02 last edited by
            #5

            @SGaist I don't think so. I tried like this, still corners has the orange(my color).

             path.addRoundedRect(QRectF(0, 0, self.width(), self.height()), self.ButtonData.Radius, self.ButtonData.Radius)  # Base background of button
            painter.drawPath(path)  # I need to draw it else color will be changed
            
            if self.AnimateEnabled:
                painter.setBrush(QBrush(QColor(231, 231, 231)))
                path.addRoundedRect(QRectF(0, 0, 0, self.height()),self.ButtonData.Radius, self.ButtonData.Radius) # Changed here (setted width to 0)
                painter.drawPath(path)
            
            
            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 14 Jul 2022, 05:56 last edited by
              #6

              Can you provide a complete minimal script that shows this ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              E 2 Replies Last reply 14 Jul 2022, 09:09
              0
              • S SGaist
                14 Jul 2022, 05:56

                Can you provide a complete minimal script that shows this ?

                E Offline
                E Offline
                Emrecp
                wrote on 14 Jul 2022, 09:09 last edited by Emrecp
                #7

                @SGaist Sure, when run it take a screenshoot and zoom in to see closely.
                Note:
                PySide6 version: 6.3.0
                Python: 3.9.7

                # -*- 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 Button(QPushButton):
                    Radius = 10
                    def __init__(self, *args, **kwargs):
                        super().__init__(*args, **kwargs)
                        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
                
                    def paintEvent(self, event: QPaintEvent):
                        painter = QPainter(self)
                        painter.setRenderHint(QPainter.Antialiasing)
                        path = QPainterPath()
                        painter.setBrush(QBrush(QColor(255, 111, 42)))
                        painter.setPen(Qt.NoPen)
                
                        path.addRoundedRect(QRectF(0, 0, self.width(), self.height()), self.Radius, self.Radius)  # Base background of button
                        painter.drawPath(path)  # I need to draw it else color will be changed
                
                        painter.setBrush(QBrush(QColor(231, 231, 231)))
                        #path.addRoundedRect(QRectF(0, 0, int(self.width() * self.AnimateVal / 100.00), self.height()),self.ButtonData.Radius, self.ButtonData.Radius)
                        path.addRoundedRect(QRectF(0, 0, 0, self.height()), self.Radius, self.Radius)
                        painter.drawPath(path)
                
                if __name__ == "__main__":
                    app = QApplication(sys.argv)
                    wind = QMainWindow()
                    wind.setStyleSheet("QMainWindow{background-color:rgb(247,247,250)}")
                    wind.resize(150, 80)
                    wid = QWidget()
                    lay = QHBoxLayout(wid)
                    lay.setAlignment(Qt.AlignCenter)
                
                    mycustombutton = Button()
                    lay.addWidget(mycustombutton)
                    wind.setCentralWidget(wid)
                    wind.show()
                    sys.exit(app.exec())
                
                1 Reply Last reply
                0
                • N Offline
                  N Offline
                  ndias
                  wrote on 14 Jul 2022, 09:50 last edited by
                  #8

                  Hi @Emrecp ,

                  Why you don't use animations to get the desired effect? I think you don't need to use QPaintEvent.

                  Please check bellow a sample app I used before with animated button. Feel free to make any necessary changes. ;)

                  # Import the necessary modules required
                  import sys
                  
                  from PySide6.QtWidgets import *
                  from PySide6.QtGui import *
                  from PySide6.QtCore import *
                  
                  class animatedButton(QPushButton):
                      '''
                      Button containing animated background with gradient moving from left to right on hover and
                      backward on leave
                      '''
                      def __init__(self, str: str, parent=None):
                          super().__init__(parent)
                  
                          self.setText(str)
                          self.setMinimumSize(50, 50)
                  
                          self.color1 = "#0DF2C9"
                          self.color2 = "#4EC5F1"
                  
                          self._animationHover = QVariantAnimation(self)
                          self._animationHover.setDuration(200)
                          self._animationHover.setStartValue(0.0)
                          self._animationHover.setEndValue(1.0)
                          self._animationHover.valueChanged.connect(self._setButtonStyleHover)
                  
                          self._animationPressed = QVariantAnimation(self)
                          self._animationPressed.setDuration(100)
                          self._animationPressed.setStartValue(0.0)
                          self._animationPressed.setEndValue(1.0)
                          self._animationPressed.valueChanged.connect(self._setButtonStylePressed)
                  
                          self._setButtonStyleHover(self._animationHover.startValue()) # set button initial style
                  
                      def setColor1(self, color: str):
                          """ :param str color: hex color code, SVG color keyword names or other color definition """
                          self.color1 = color
                          self._setButtonStyleHover(self._animationHover.startValue())
                      def setColor2(self, color: str):
                          """ :param str color: hex color code, SVG color keyword names or other color definition """
                          self.color2 = color
                          self._setButtonStyleHover(self._animationHover.startValue())
                  
                      def _setButtonStyleHover(self, value):
                          qss = """
                                padding: 12px;
                                font: 75 14pt "Microsoft YaHei UI";
                                font-weight: bold;
                                color: rgb(255, 255, 255);
                                border-style: solid;
                                border-radius:21px;
                                """
                          if value == 0:
                              gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:{value} {color2}, stop: 1.0 {color1});".format(
                                      color1=self.color1, color2=self.color2, value=value )
                          elif value == 1:
                              gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop: 1.0 {color2});".format(
                                      color1=self.color1, color2=self.color2, value=value )
                          else:
                              gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop:{value} {color2}, stop: 1.0 {color1});".format(
                                      color1=self.color1, color2=self.color2, value=value )
                          qss += gradient
                          self.setStyleSheet(qss)
                  
                      def _setButtonStylePressed(self, value):
                          qss = """
                                padding: 12px;
                                font: 75 14pt "Microsoft YaHei UI";
                                font-weight: bold;
                                color: rgb(255, 255, 255);
                                border-style: solid;
                                border-radius:21px;
                                """
                          if value == 0:
                              gradient = "background-color: {color}".format(color=self.color2)
                          elif value == 1:
                              gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop: 1.0 {color2});".format(
                                      color1=self.color1, color2=self.color2, value=value )
                          else:
                              gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop: {value} {color2});".format(
                                      color1=self.color1, color2=self.color2, value=value )
                          qss += gradient
                          self.setStyleSheet(qss)
                  
                      def enterEvent(self, event):
                          self._animationHover.setDirection(QAbstractAnimation.Forward)
                          self._animationHover.start()
                          super().enterEvent(event)
                  
                      def leaveEvent(self, event):
                          self._animationHover.setDirection(QAbstractAnimation.Backward)
                          self._animationHover.start()
                          super().leaveEvent(event)
                  
                      def mousePressEvent(self, event):
                          self._animationPressed.setDirection(QAbstractAnimation.Backward)
                          self._animationPressed.start()
                          super().mousePressEvent(event)
                  
                      def mouseReleaseEvent(self, event):
                          self._animationPressed.setDirection(QAbstractAnimation.Forward)
                          self._animationPressed.start()
                          super().mouseReleaseEvent(event)
                  

                  Best regards

                  E 1 Reply Last reply 14 Jul 2022, 11:19
                  2
                  • N ndias
                    14 Jul 2022, 09:50

                    Hi @Emrecp ,

                    Why you don't use animations to get the desired effect? I think you don't need to use QPaintEvent.

                    Please check bellow a sample app I used before with animated button. Feel free to make any necessary changes. ;)

                    # Import the necessary modules required
                    import sys
                    
                    from PySide6.QtWidgets import *
                    from PySide6.QtGui import *
                    from PySide6.QtCore import *
                    
                    class animatedButton(QPushButton):
                        '''
                        Button containing animated background with gradient moving from left to right on hover and
                        backward on leave
                        '''
                        def __init__(self, str: str, parent=None):
                            super().__init__(parent)
                    
                            self.setText(str)
                            self.setMinimumSize(50, 50)
                    
                            self.color1 = "#0DF2C9"
                            self.color2 = "#4EC5F1"
                    
                            self._animationHover = QVariantAnimation(self)
                            self._animationHover.setDuration(200)
                            self._animationHover.setStartValue(0.0)
                            self._animationHover.setEndValue(1.0)
                            self._animationHover.valueChanged.connect(self._setButtonStyleHover)
                    
                            self._animationPressed = QVariantAnimation(self)
                            self._animationPressed.setDuration(100)
                            self._animationPressed.setStartValue(0.0)
                            self._animationPressed.setEndValue(1.0)
                            self._animationPressed.valueChanged.connect(self._setButtonStylePressed)
                    
                            self._setButtonStyleHover(self._animationHover.startValue()) # set button initial style
                    
                        def setColor1(self, color: str):
                            """ :param str color: hex color code, SVG color keyword names or other color definition """
                            self.color1 = color
                            self._setButtonStyleHover(self._animationHover.startValue())
                        def setColor2(self, color: str):
                            """ :param str color: hex color code, SVG color keyword names or other color definition """
                            self.color2 = color
                            self._setButtonStyleHover(self._animationHover.startValue())
                    
                        def _setButtonStyleHover(self, value):
                            qss = """
                                  padding: 12px;
                                  font: 75 14pt "Microsoft YaHei UI";
                                  font-weight: bold;
                                  color: rgb(255, 255, 255);
                                  border-style: solid;
                                  border-radius:21px;
                                  """
                            if value == 0:
                                gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:{value} {color2}, stop: 1.0 {color1});".format(
                                        color1=self.color1, color2=self.color2, value=value )
                            elif value == 1:
                                gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop: 1.0 {color2});".format(
                                        color1=self.color1, color2=self.color2, value=value )
                            else:
                                gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop:{value} {color2}, stop: 1.0 {color1});".format(
                                        color1=self.color1, color2=self.color2, value=value )
                            qss += gradient
                            self.setStyleSheet(qss)
                    
                        def _setButtonStylePressed(self, value):
                            qss = """
                                  padding: 12px;
                                  font: 75 14pt "Microsoft YaHei UI";
                                  font-weight: bold;
                                  color: rgb(255, 255, 255);
                                  border-style: solid;
                                  border-radius:21px;
                                  """
                            if value == 0:
                                gradient = "background-color: {color}".format(color=self.color2)
                            elif value == 1:
                                gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop: 1.0 {color2});".format(
                                        color1=self.color1, color2=self.color2, value=value )
                            else:
                                gradient = "background-color: qlineargradient(spread: pad, x1:0, y1:0, x2:1, y2:0, stop:0 {color1}, stop: {value} {color2});".format(
                                        color1=self.color1, color2=self.color2, value=value )
                            qss += gradient
                            self.setStyleSheet(qss)
                    
                        def enterEvent(self, event):
                            self._animationHover.setDirection(QAbstractAnimation.Forward)
                            self._animationHover.start()
                            super().enterEvent(event)
                    
                        def leaveEvent(self, event):
                            self._animationHover.setDirection(QAbstractAnimation.Backward)
                            self._animationHover.start()
                            super().leaveEvent(event)
                    
                        def mousePressEvent(self, event):
                            self._animationPressed.setDirection(QAbstractAnimation.Backward)
                            self._animationPressed.start()
                            super().mousePressEvent(event)
                    
                        def mouseReleaseEvent(self, event):
                            self._animationPressed.setDirection(QAbstractAnimation.Forward)
                            self._animationPressed.start()
                            super().mouseReleaseEvent(event)
                    

                    Best regards

                    E Offline
                    E Offline
                    Emrecp
                    wrote on 14 Jul 2022, 11:19 last edited by
                    #9

                    @ndias Well thanks for your answer. Using setStyleSheet is good idea but I think it's not advanced better than custom paintEvent. Still don't know why corners has first brush color?

                    And I don't know hot to make 19th button on this website Website
                    Can someone help me to this too?
                    Thanks!

                    1 Reply Last reply
                    0
                    • S SGaist
                      14 Jul 2022, 05:56

                      Can you provide a complete minimal script that shows this ?

                      E Offline
                      E Offline
                      Emrecp
                      wrote on 14 Jul 2022, 21:07 last edited by
                      #10

                      @SGaist I found the problem. When I remove

                         painter.setRenderHint(QPainter.Antialiasing)
                      

                      The colors on the corner gone. But why? Anyway to use antialiasing?

                      1 Reply Last reply
                      0
                      • S Offline
                        S Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on 15 Jul 2022, 19:42 last edited by
                        #11

                        The smoothing done for the antialiasing will not be the same for all colors.

                        Interested in AI ? www.idiap.ch
                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0

                        6/11

                        14 Jul 2022, 05:56

                        • Login

                        • Login or register to search.
                        6 out of 11
                        • First post
                          6/11
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved