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

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.
  • EmrecpE Offline
    EmrecpE Offline
    Emrecp
    wrote on 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
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on 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

      EmrecpE 1 Reply Last reply
      0
      • SGaistS SGaist

        Hi,

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

        EmrecpE Offline
        EmrecpE Offline
        Emrecp
        wrote on 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
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on 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

          EmrecpE 1 Reply Last reply
          0
          • SGaistS SGaist

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

            EmrecpE Offline
            EmrecpE Offline
            Emrecp
            wrote on 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
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on 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

              EmrecpE 2 Replies Last reply
              0
              • SGaistS SGaist

                Can you provide a complete minimal script that shows this ?

                EmrecpE Offline
                EmrecpE Offline
                Emrecp
                wrote on 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
                • ndiasN Offline
                  ndiasN Offline
                  ndias
                  wrote on 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

                  EmrecpE 1 Reply Last reply
                  2
                  • ndiasN ndias

                    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

                    EmrecpE Offline
                    EmrecpE Offline
                    Emrecp
                    wrote on 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
                    • SGaistS SGaist

                      Can you provide a complete minimal script that shows this ?

                      EmrecpE Offline
                      EmrecpE Offline
                      Emrecp
                      wrote on 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
                      • SGaistS Offline
                        SGaistS Offline
                        SGaist
                        Lifetime Qt Champion
                        wrote on 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

                        • Login

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