Re: How to make a circular button?

Maurizio Berti <[email protected]>
Newsgroups gmane.comp.python.pyqt-pykde
Message-ID <CAPn+-XQ1Cf+v3ixyy8bM-79ABFPUa8qko6M5fcTEYE68FKAX-Q@mail.gmail.com>
You'll have to subclass QPushButton, provide a way to set/change the
radius, and at least override the paintEvent to actually draw the circle
and possibly the sizeHint to report the preferred size of the button (based
on the radius), unless you to set a fixed size when setting the radius.

In the following example I've used two gradients to get a round button with
borders that have a "shadow" effect: it's composed of a conical gradient
with a superimposed radial gradient to "mask" the center of the conical.

class CircleButton(QtWidgets.QPushButton):
    def __init__(self, radius=None, parent=None):
        super().__init__(parent)
        if radius is None:
            radius = self.font().pointSize() * 2
        self.setRadius(radius)

        # use the palette as source for the colors
        palette = self.palette()
        light = palette.color(palette.Light)
        midlight = palette.color(palette.Midlight)
        mid = palette.color(palette.Mid)
        dark = palette.color(palette.Dark)

        # a radial gradient for the "shadow effect" when button is unpressed
        self.backgroundUp = QtGui.QConicalGradient(.5, .5, 135)

self.backgroundUp.setCoordinateMode(self.backgroundUp.ObjectBoundingMode)
        self.backgroundUp.setStops([
            (0.0, light),
            (0.3, dark),
            (0.6, dark),
            (1.0, light),
        ])

        # the same as above, but inverted for pressed state
        self.backgroundDown = QtGui.QConicalGradient(.5, .5, 315)

self.backgroundDown.setCoordinateMode(self.backgroundDown.ObjectBoundingMode)
        self.backgroundDown.setStops(self.backgroundUp.stops())

        # a "mask" for the conical gradient
        self.ringShapeDown = QtGui.QRadialGradient(.5, .5, .5)

self.ringShapeDown.setCoordinateMode(self.ringShapeDown.ObjectBoundingMode)
        self.ringShapeDown.setStops([
            (0.7536231884057971, midlight),
            (0.7960662525879917, QtCore.Qt.transparent),
        ])

        self.ringShapeUp = QtGui.QRadialGradient(.5, .5, .5)

self.ringShapeUp.setCoordinateMode(self.ringShapeUp.ObjectBoundingMode)
        self.ringShapeUp.setStops([
            (0.7536231884057971, mid),
            (0.7960662525879917, QtCore.Qt.transparent),
            (0.9627329192546584, QtCore.Qt.transparent),
        ])

    def getButtonRect(self):
        # just a helper function to avoid repetitions
        size = min(self.width(), self.height()) - 1
        rect = QtCore.QRect(0, 0, size, size)
        rect.moveCenter(self.rect().center())
        return rect

    def mousePressEvent(self, event):
        # ensure that the click happens within the circle
        path = QtGui.QPainterPath()
        path.addEllipse(QtCore.QRectF(self.getButtonRect()))
        if path.contains(event.pos()):
            super().mousePressEvent(event)

    def setRadius(self, radius):
        self.radius = radius
        # notify the layout manager that the size hint has changed
        self.updateGeometry()

    def sizeHint(self):
        return QtCore.QSize(self.radius, self.radius)

    def hasHeightForWidth(self):
        return True

    def heightForWidth(self, width):
        return width

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setRenderHints(qp.Antialiasing)
        qp.translate(.5, .5)
        qp.setPen(QtCore.Qt.NoPen)
        rect = self.getButtonRect()
        if self.isDown() or self.isChecked():
            qp.setBrush(self.backgroundDown)
            qp.drawEllipse(rect)
            qp.setBrush(self.ringShapeDown)
            qp.drawEllipse(rect)
        else:
            qp.setBrush(self.backgroundUp)
            qp.drawEllipse(rect)
            qp.setBrush(self.ringShapeUp)
            qp.drawEllipse(rect)

Il giorno mar 3 mar 2020 alle ore 13:08 Souvik Dutta Chowdhury <
[email protected]> ha scritto:

> I want to make a perfect circular button and want to set a custom radius.
> How to do it?
> _______________________________________________
> PyQt mailing list    [email protected]
> https://www.riverbankcomputing.com/mailman/listinfo/pyqt
>


-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net

_______________________________________________
PyQt mailing list    [email protected]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.