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
Forum Updated to NodeBB v4.3 + New Features

Custom Button, paintEvent issue

Scheduled Pinned Locked Moved Unsolved Qt for Python
pyqt5pyside6custom widgetpainteventbutton
11 Posts 3 Posters 1.2k Views 2 Watching
  • 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

                        8/11

                        14 Jul 2022, 09:50

                        • Login

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