Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Creating circular QPushbutton
Forum Updated to NodeBB v4.3 + New Features

Creating circular QPushbutton

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 4 Posters 11.5k Views 1 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.
  • KiraK Kira

    Hello All,
    Qt pushbutton is rectangular in shape by default. I am using QCommonstyle to provide an arrow button to pushbutton which is circular in shape. My problem is that when I try to assign an icon to the button it does not turn to exact size of the icon ie. I want my push button to turn to the size of the icon

    QCommonStyle style;
        _ui->Forward->setIconSize({ _ui->btnXForward->width(),_ui->btnXForward->height() });
        _ui->Forward->setIcon(style.standardIcon(QStyle::SP_ArrowForward));
    

    a540dc2d-7333-41ea-80b9-4a86bcd229ba-image.png

    sankarapandiyanS Offline
    sankarapandiyanS Offline
    sankarapandiyan
    wrote on last edited by
    #2

    @Kira

    use this in button style sheet

    QPushButton {
    color: #333;
    border: 2px solid #555;
    border-radius: 20px;
    border-style: outset;
    background: qradialgradient(
    cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,
    radius: 1.35, stop: 0 #fff, stop: 1 #888
    );
    padding: 5px;
    }
    
    QPushButton:hover {
    background: qradialgradient(
    cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,
    radius: 1.35, stop: 0 #fff, stop: 1 #bbb
    );
    }
    
    KiraK 1 Reply Last reply
    1
    • sankarapandiyanS sankarapandiyan

      @Kira

      use this in button style sheet

      QPushButton {
      color: #333;
      border: 2px solid #555;
      border-radius: 20px;
      border-style: outset;
      background: qradialgradient(
      cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,
      radius: 1.35, stop: 0 #fff, stop: 1 #888
      );
      padding: 5px;
      }
      
      QPushButton:hover {
      background: qradialgradient(
      cx: 0.3, cy: -0.4, fx: 0.3, fy: -0.4,
      radius: 1.35, stop: 0 #fff, stop: 1 #bbb
      );
      }
      
      KiraK Offline
      KiraK Offline
      Kira
      wrote on last edited by
      #3

      @sankarapandiyan: Due you have sample example for the same, I tried setting the property but it did not work for me

      sankarapandiyanS 1 Reply Last reply
      0
      • VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by
        #4

        You can use setMask. Something like:

        class RoundButton : public QPushButton{
            Q_DISABLE_COPY(RoundButton)
        public:
            using QPushButton::QPushButton;
        protected:
            void resizeEvent(QResizeEvent *event) override{
                QPushButton::resizeEvent(event);
                const QRect buttonRect = rect();
                setMask(QRegion(buttonRect.x(),buttonRect.y(),buttonRect.width(),buttonRect.height(),QRegion::Ellipse));
            }
        };
        

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        KiraK 1 Reply Last reply
        6
        • KiraK Kira

          @sankarapandiyan: Due you have sample example for the same, I tried setting the property but it did not work for me

          sankarapandiyanS Offline
          sankarapandiyanS Offline
          sankarapandiyan
          wrote on last edited by
          #5

          @Kira sure .. I will share some sample code for you ..

          https://www.dropbox.com/s/ggrpv4zo1icdj14/circle_btn.zip?dl=0

          KiraK 1 Reply Last reply
          2
          • sankarapandiyanS sankarapandiyan

            @Kira sure .. I will share some sample code for you ..

            https://www.dropbox.com/s/ggrpv4zo1icdj14/circle_btn.zip?dl=0

            KiraK Offline
            KiraK Offline
            Kira
            wrote on last edited by
            #6

            @sankarapandiyan @VRonin: Thanks for the revert
            @sankarapandiyan: I tried your code it's working but it works if I have pushbutton of fixed size
            If I try to change the dimensions the shape changes.
            Also, the approach doesn't seems to work if I put it into layout.

            1 Reply Last reply
            0
            • VRoninV VRonin

              You can use setMask. Something like:

              class RoundButton : public QPushButton{
                  Q_DISABLE_COPY(RoundButton)
              public:
                  using QPushButton::QPushButton;
              protected:
                  void resizeEvent(QResizeEvent *event) override{
                      QPushButton::resizeEvent(event);
                      const QRect buttonRect = rect();
                      setMask(QRegion(buttonRect.x(),buttonRect.y(),buttonRect.width(),buttonRect.height(),QRegion::Ellipse));
                  }
              };
              
              KiraK Offline
              KiraK Offline
              Kira
              wrote on last edited by
              #7

              @VRonin: Thanks a lot for your help.
              But I can see some lines in the button and it is not completely circular
              d7caa65f-ffe5-4152-8dfc-e72e99b25314-image.png
              As we can see four lines at the corner of the button

              VRoninV 1 Reply Last reply
              0
              • KiraK Kira

                @VRonin: Thanks a lot for your help.
                But I can see some lines in the button and it is not completely circular
                d7caa65f-ffe5-4152-8dfc-e72e99b25314-image.png
                As we can see four lines at the corner of the button

                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #8

                @Kira said in Creating circular QPushbutton:

                As we can see four lines at the corner of the button

                That just the border of the button. you can either disable the border with the stylesheet or change the call to setMask

                setMask(QRegion(buttonRect.x(),buttonRect.y(),buttonRect.width()-x,buttonRect.height()-x,QRegion::Ellipse));

                where x is the size of the border

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                1 Reply Last reply
                2
                • J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by J.Hilk
                  #9

                  an other approach:

                  #ifndef CIRCULARBUTTON_H
                  #define CIRCULARBUTTON_H
                  
                  #include <QPushButton>
                  
                  class CircularButton : public QPushButton
                  {
                      Q_OBJECT
                  public:
                      explicit CircularButton(QWidget *parent = nullptr);
                  
                  signals:
                  
                  public slots:
                  
                  protected:
                      virtual void paintEvent(QPaintEvent *) override;
                      virtual void resizeEvent(QResizeEvent *)override;
                  };
                  
                  #endif // CIRCULARBUTTON_H
                  
                  
                  #include "circularbutton.h"
                  
                  #include <QPainter>
                  
                  CircularButton::CircularButton(QWidget *parent) : QPushButton(parent)
                  {
                  
                  }
                  
                  void CircularButton::paintEvent(QPaintEvent *)
                  {
                      //Do not paint base implementation -> no styles are applied
                  
                      QColor background = isDown() ? QColor("grey") : QColor("lightgrey");
                      int diameter = qMin(height(), width());
                  
                      QPainter painter(this);
                      painter.setRenderHint(QPainter::Antialiasing, false);
                      painter.translate(width() / 2, height() / 2);
                  
                      painter.setPen(QPen(QColor("black"), 2));
                      painter.setBrush(QBrush(background));
                      painter.drawEllipse(QRect(-diameter / 2, -diameter / 2, diameter, diameter));
                  
                  }
                  
                  void CircularButton::resizeEvent(QResizeEvent *e)
                  {
                      QPushButton::resizeEvent(e);
                      int diameter = qMin(height(), width())+4 ;
                      int xOff =(width() -diameter ) / 2;
                      int yOff =(height() - diameter) / 2;
                      setMask(QRegion(xOff,yOff, diameter, diameter,QRegion::Ellipse));
                  }
                  

                  Edit:
                  added the mask, like @VRonin suggested


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  VRoninV 1 Reply Last reply
                  5
                  • J.HilkJ J.Hilk

                    an other approach:

                    #ifndef CIRCULARBUTTON_H
                    #define CIRCULARBUTTON_H
                    
                    #include <QPushButton>
                    
                    class CircularButton : public QPushButton
                    {
                        Q_OBJECT
                    public:
                        explicit CircularButton(QWidget *parent = nullptr);
                    
                    signals:
                    
                    public slots:
                    
                    protected:
                        virtual void paintEvent(QPaintEvent *) override;
                        virtual void resizeEvent(QResizeEvent *)override;
                    };
                    
                    #endif // CIRCULARBUTTON_H
                    
                    
                    #include "circularbutton.h"
                    
                    #include <QPainter>
                    
                    CircularButton::CircularButton(QWidget *parent) : QPushButton(parent)
                    {
                    
                    }
                    
                    void CircularButton::paintEvent(QPaintEvent *)
                    {
                        //Do not paint base implementation -> no styles are applied
                    
                        QColor background = isDown() ? QColor("grey") : QColor("lightgrey");
                        int diameter = qMin(height(), width());
                    
                        QPainter painter(this);
                        painter.setRenderHint(QPainter::Antialiasing, false);
                        painter.translate(width() / 2, height() / 2);
                    
                        painter.setPen(QPen(QColor("black"), 2));
                        painter.setBrush(QBrush(background));
                        painter.drawEllipse(QRect(-diameter / 2, -diameter / 2, diameter, diameter));
                    
                    }
                    
                    void CircularButton::resizeEvent(QResizeEvent *e)
                    {
                        QPushButton::resizeEvent(e);
                        int diameter = qMin(height(), width())+4 ;
                        int xOff =(width() -diameter ) / 2;
                        int yOff =(height() - diameter) / 2;
                        setMask(QRegion(xOff,yOff, diameter, diameter,QRegion::Ellipse));
                    }
                    

                    Edit:
                    added the mask, like @VRonin suggested

                    VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by VRonin
                    #10

                    @J-Hilk said in Creating circular QPushbutton:

                    an other approach

                    Using this approach clicking a point inside CircularButton::rect but outside the pained circle would still trigger the click so you need to combine this with the setMask implementation

                    Edit: code fixed

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    2
                    • KiraK Offline
                      KiraK Offline
                      Kira
                      wrote on last edited by
                      #11

                      @J-Hilk @VRonin @sankarapandiyan : Thanks everyone for the clarification :)

                      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