1#!/usr/bin/env python
2
3"""
4polygonwidget.py
5
6A PyQt custom widget example for Qt Designer.
7
8Copyright (C) 2006 David Boddie <david@boddie.org.uk>
9Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24"""
25
26import math
27
28from PyQt5.QtCore import pyqtProperty, pyqtSlot, QPointF, QSize
29from PyQt5.QtGui import QBrush, QColor, QPainter, QPainterPath, QRadialGradient
30from PyQt5.QtWidgets import QApplication, QWidget
31
32
33class PolygonWidget(QWidget):
34    """PolygonWidget(QWidget)
35
36    Provides a custom widget to display a polygon with properties and slots
37    that can be used to customize its appearance.
38    """
39
40    def __init__(self, parent=None):
41
42        super(PolygonWidget, self).__init__(parent)
43
44        self._sides = 5
45        self._innerRadius = 20
46        self._outerRadius = 50
47        self._angle = 0
48
49        self.createPath()
50
51        self._innerColor = QColor(255, 255, 128)
52        self._outerColor = QColor(255, 0, 128)
53
54        self.createGradient()
55
56    def paintEvent(self, event):
57
58        painter = QPainter()
59        painter.begin(self)
60        painter.setRenderHint(QPainter.Antialiasing)
61        painter.setBrush(QBrush(QColor(192, 192, 255)))
62        painter.drawRect(event.rect())
63
64        painter.translate(self.width()/2.0, self.height()/2.0)
65        painter.rotate(self._angle)
66        painter.setBrush(QBrush(self.gradient))
67        painter.drawPath(self.path)
68        painter.end()
69
70    def sizeHint(self):
71
72        return QSize(2*self._outerRadius + 20, 2*self._outerRadius + 20)
73
74    def createPath(self):
75
76        self.path = QPainterPath()
77        angle = 2*math.pi/self._sides
78        self.path.moveTo(self._outerRadius, 0)
79        for step in range(1, self._sides + 1):
80            self.path.lineTo(
81                self._innerRadius * math.cos((step - 0.5) * angle),
82                self._innerRadius * math.sin((step - 0.5) * angle)
83                )
84            self.path.lineTo(
85                self._outerRadius * math.cos(step * angle),
86                self._outerRadius * math.sin(step * angle)
87                )
88        self.path.closeSubpath()
89
90    def createGradient(self):
91
92        center = QPointF(0, 0)
93        self.gradient = QRadialGradient(center, self._outerRadius, center)
94        self.gradient.setColorAt(0.5, QColor(self._innerColor))
95        self.gradient.setColorAt(1.0, QColor(self._outerColor))
96
97    # The angle property is implemented using the getAngle() and setAngle()
98    # methods.
99
100    def getAngle(self):
101        return self._angle
102
103    # The setAngle() setter method is also a slot.
104    @pyqtSlot(int)
105    def setAngle(self, angle):
106        self._angle = min(max(0, angle), 360)
107        self.update()
108
109    angle = pyqtProperty(int, getAngle, setAngle)
110
111    # The innerRadius property is implemented using the getInnerRadius() and
112    # setInnerRadius() methods.
113
114    def getInnerRadius(self):
115        return self._innerRadius
116
117    # The setInnerRadius() setter method is also a slot.
118    @pyqtSlot(int)
119    def setInnerRadius(self, radius):
120        self._innerRadius = radius
121        self.createPath()
122        self.createGradient()
123        self.update()
124
125    innerRadius = pyqtProperty(int, getInnerRadius, setInnerRadius)
126
127    # The outerRadius property is implemented using the getOuterRadius() and
128    # setOuterRadius() methods.
129
130    def getOuterRadius(self):
131        return self._outerRadius
132
133    # The setOuterRadius() setter method is also a slot.
134    @pyqtSlot(int)
135    def setOuterRadius(self, radius):
136        self._outerRadius = radius
137        self.createPath()
138        self.createGradient()
139        self.update()
140
141    outerRadius = pyqtProperty(int, getOuterRadius, setOuterRadius)
142
143    # The numberOfSides property is implemented using the getNumberOfSides()
144    # and setNumberOfSides() methods.
145
146    def getNumberOfSides(self):
147        return self._sides
148
149    # The setNumberOfSides() setter method is also a slot.
150    @pyqtSlot(int)
151    def setNumberOfSides(self, sides):
152        self._sides = max(3, sides)
153        self.createPath()
154        self.update()
155
156    numberOfSides = pyqtProperty(int, getNumberOfSides, setNumberOfSides)
157
158    # The innerColor property is implemented using the getInnerColor() and
159    # setInnerColor() methods.
160
161    def getInnerColor(self):
162        return self._innerColor
163
164    def setInnerColor(self, color):
165        self._innerColor = max(3, color)
166        self.createGradient()
167        self.update()
168
169    innerColor = pyqtProperty(QColor, getInnerColor, setInnerColor)
170
171    # The outerColor property is implemented using the getOuterColor() and
172    # setOuterColor() methods.
173
174    def getOuterColor(self):
175        return self._outerColor
176
177    def setOuterColor(self, color):
178        self._outerColor = color
179        self.createGradient()
180        self.update()
181
182    outerColor = pyqtProperty(QColor, getOuterColor, setOuterColor)
183
184
185if __name__ == "__main__":
186
187    import sys
188
189    app = QApplication(sys.argv)
190    window = PolygonWidget()
191    window.show()
192    sys.exit(app.exec_())
193