Creating circular QPushbutton
-
wrote on 20 Feb 2020, 09:48 last edited by
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 iconQCommonStyle style; _ui->Forward->setIconSize({ _ui->btnXForward->width(),_ui->btnXForward->height() }); _ui->Forward->setIcon(style.standardIcon(QStyle::SP_ArrowForward));
-
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 iconQCommonStyle style; _ui->Forward->setIconSize({ _ui->btnXForward->width(),_ui->btnXForward->height() }); _ui->Forward->setIcon(style.standardIcon(QStyle::SP_ArrowForward));
wrote on 20 Feb 2020, 09:52 last edited byuse 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 ); }
-
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 ); }
wrote on 20 Feb 2020, 11:21 last edited by@sankarapandiyan: Due you have sample example for the same, I tried setting the property but it did not work for me
-
wrote on 20 Feb 2020, 12:01 last edited by
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)); } };
-
@sankarapandiyan: Due you have sample example for the same, I tried setting the property but it did not work for me
wrote on 21 Feb 2020, 04:50 last edited by@Kira sure .. I will share some sample code for you ..
https://www.dropbox.com/s/ggrpv4zo1icdj14/circle_btn.zip?dl=0
-
@Kira sure .. I will share some sample code for you ..
https://www.dropbox.com/s/ggrpv4zo1icdj14/circle_btn.zip?dl=0
wrote on 24 Feb 2020, 05:53 last edited by@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. -
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)); } };
-
@VRonin: Thanks a lot for your help.
But I can see some lines in the button and it is not completely circular
As we can see four lines at the corner of the buttonwrote on 24 Feb 2020, 09:47 last edited by@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 -
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 -
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 suggestedwrote on 24 Feb 2020, 10:16 last edited by VRonin@J-Hilk said in Creating circular QPushbutton:
an other approach
Using this approach clicking a point insideCircularButton::rect
but outside the pained circle would still trigger the click so you need to combine this with thesetMask
implementationEdit: code fixed
-
wrote on 25 Feb 2020, 04:59 last edited by
@J-Hilk @VRonin @sankarapandiyan : Thanks everyone for the clarification :)
1/11