[PyQt] How to make a circular button?
Maurizio Berti
maurizio.berti at gmail.com
Tue Mar 3 13:22:11 GMT 2020
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 <
souvik.viksou at outlook.com> ha scritto:
> I want to make a perfect circular button and want to set a custom radius.
> How to do it?
> _______________________________________________
> PyQt mailing list PyQt at riverbankcomputing.com
> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20200303/d9e425c4/attachment.htm>
More information about the PyQt
mailing list