1#!/usr/bin/env python
2
3
4#############################################################################
5##
6## Copyright (C) 2013 Riverbank Computing Limited.
7## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
8## All rights reserved.
9##
10## This file is part of the examples of PyQt.
11##
12## $QT_BEGIN_LICENSE:BSD$
13## You may use this file under the terms of the BSD license as follows:
14##
15## "Redistribution and use in source and binary forms, with or without
16## modification, are permitted provided that the following conditions are
17## met:
18##   * Redistributions of source code must retain the above copyright
19##     notice, this list of conditions and the following disclaimer.
20##   * Redistributions in binary form must reproduce the above copyright
21##     notice, this list of conditions and the following disclaimer in
22##     the documentation and/or other materials provided with the
23##     distribution.
24##   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
25##     the names of its contributors may be used to endorse or promote
26##     products derived from this software without specific prior written
27##     permission.
28##
29## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
40## $QT_END_LICENSE$
41##
42#############################################################################
43
44
45from PyQt5.QtCore import QPoint, QRect, QSize, Qt
46from PyQt5.QtGui import (QBrush, QConicalGradient, QLinearGradient, QPainter,
47        QPainterPath, QPalette, QPen, QPixmap, QPolygon, QRadialGradient)
48from PyQt5.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout,
49        QLabel, QSpinBox, QWidget)
50
51import basicdrawing_rc
52
53
54class RenderArea(QWidget):
55    points = QPolygon([
56        QPoint(10, 80),
57        QPoint(20, 10),
58        QPoint(80, 30),
59        QPoint(90, 70)
60    ])
61
62    Line, Points, Polyline, Polygon, Rect, RoundedRect, Ellipse, Arc, Chord, \
63            Pie, Path, Text, Pixmap = range(13)
64
65    def __init__(self, parent=None):
66        super(RenderArea, self).__init__(parent)
67
68        self.pen = QPen()
69        self.brush = QBrush()
70        self.pixmap = QPixmap()
71
72        self.shape = RenderArea.Polygon
73        self.antialiased = False
74        self.transformed = False
75        self.pixmap.load(':/images/qt-logo.png')
76
77        self.setBackgroundRole(QPalette.Base)
78        self.setAutoFillBackground(True)
79
80    def minimumSizeHint(self):
81        return QSize(100, 100)
82
83    def sizeHint(self):
84        return QSize(400, 200)
85
86    def setShape(self, shape):
87        self.shape = shape
88        self.update()
89
90    def setPen(self, pen):
91        self.pen = pen
92        self.update()
93
94    def setBrush(self, brush):
95        self.brush = brush
96        self.update()
97
98    def setAntialiased(self, antialiased):
99        self.antialiased = antialiased
100        self.update()
101
102    def setTransformed(self, transformed):
103        self.transformed = transformed
104        self.update()
105
106    def paintEvent(self, event):
107        rect = QRect(10, 20, 80, 60)
108
109        path = QPainterPath()
110        path.moveTo(20, 80)
111        path.lineTo(20, 30)
112        path.cubicTo(80, 0, 50, 50, 80, 80)
113
114        startAngle = 30 * 16
115        arcLength = 120 * 16
116
117        painter = QPainter(self)
118        painter.setPen(self.pen)
119        painter.setBrush(self.brush)
120        if self.antialiased:
121            painter.setRenderHint(QPainter.Antialiasing)
122
123        for x in range(0, self.width(), 100):
124            for y in range(0, self.height(), 100):
125                painter.save()
126                painter.translate(x, y)
127                if self.transformed:
128                    painter.translate(50, 50)
129                    painter.rotate(60.0)
130                    painter.scale(0.6, 0.9)
131                    painter.translate(-50, -50)
132
133                if self.shape == RenderArea.Line:
134                    painter.drawLine(rect.bottomLeft(), rect.topRight())
135                elif self.shape == RenderArea.Points:
136                    painter.drawPoints(RenderArea.points)
137                elif self.shape == RenderArea.Polyline:
138                    painter.drawPolyline(RenderArea.points)
139                elif self.shape == RenderArea.Polygon:
140                    painter.drawPolygon(RenderArea.points)
141                elif self.shape == RenderArea.Rect:
142                    painter.drawRect(rect)
143                elif self.shape == RenderArea.RoundedRect:
144                    painter.drawRoundedRect(rect, 25, 25, Qt.RelativeSize)
145                elif self.shape == RenderArea.Ellipse:
146                    painter.drawEllipse(rect)
147                elif self.shape == RenderArea.Arc:
148                    painter.drawArc(rect, startAngle, arcLength)
149                elif self.shape == RenderArea.Chord:
150                    painter.drawChord(rect, startAngle, arcLength)
151                elif self.shape == RenderArea.Pie:
152                    painter.drawPie(rect, startAngle, arcLength)
153                elif self.shape == RenderArea.Path:
154                    painter.drawPath(path)
155                elif self.shape == RenderArea.Text:
156                    painter.drawText(rect, Qt.AlignCenter,
157                            "PyQt by\nRiverbank Computing")
158                elif self.shape == RenderArea.Pixmap:
159                    painter.drawPixmap(10, 10, self.pixmap)
160
161                painter.restore()
162
163        painter.setPen(self.palette().dark().color())
164        painter.setBrush(Qt.NoBrush)
165        painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
166
167
168IdRole = Qt.UserRole
169
170class Window(QWidget):
171    def __init__(self):
172        super(Window, self).__init__()
173
174        self.renderArea = RenderArea()
175
176        self.shapeComboBox = QComboBox()
177        self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
178        self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
179        self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
180        self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
181        self.shapeComboBox.addItem("Pie", RenderArea.Pie)
182        self.shapeComboBox.addItem("Chord", RenderArea.Chord)
183        self.shapeComboBox.addItem("Path", RenderArea.Path)
184        self.shapeComboBox.addItem("Line", RenderArea.Line)
185        self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
186        self.shapeComboBox.addItem("Arc", RenderArea.Arc)
187        self.shapeComboBox.addItem("Points", RenderArea.Points)
188        self.shapeComboBox.addItem("Text", RenderArea.Text)
189        self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)
190
191        shapeLabel = QLabel("&Shape:")
192        shapeLabel.setBuddy(self.shapeComboBox)
193
194        self.penWidthSpinBox = QSpinBox()
195        self.penWidthSpinBox.setRange(0, 20)
196        self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")
197
198        penWidthLabel = QLabel("Pen &Width:")
199        penWidthLabel.setBuddy(self.penWidthSpinBox)
200
201        self.penStyleComboBox = QComboBox()
202        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
203        self.penStyleComboBox.addItem("Dash", Qt.DashLine)
204        self.penStyleComboBox.addItem("Dot", Qt.DotLine)
205        self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
206        self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
207        self.penStyleComboBox.addItem("None", Qt.NoPen)
208
209        penStyleLabel = QLabel("&Pen Style:")
210        penStyleLabel.setBuddy(self.penStyleComboBox)
211
212        self.penCapComboBox = QComboBox()
213        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
214        self.penCapComboBox.addItem("Square", Qt.SquareCap)
215        self.penCapComboBox.addItem("Round", Qt.RoundCap)
216
217        penCapLabel = QLabel("Pen &Cap:")
218        penCapLabel.setBuddy(self.penCapComboBox)
219
220        self.penJoinComboBox = QComboBox()
221        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
222        self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
223        self.penJoinComboBox.addItem("Round", Qt.RoundJoin)
224
225        penJoinLabel = QLabel("Pen &Join:")
226        penJoinLabel.setBuddy(self.penJoinComboBox)
227
228        self.brushStyleComboBox = QComboBox()
229        self.brushStyleComboBox.addItem("Linear Gradient",
230                Qt.LinearGradientPattern)
231        self.brushStyleComboBox.addItem("Radial Gradient",
232                Qt.RadialGradientPattern)
233        self.brushStyleComboBox.addItem("Conical Gradient",
234                Qt.ConicalGradientPattern)
235        self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
236        self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
237        self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
238        self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
239        self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
240        self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
241        self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
242        self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
243        self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
244        self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
245        self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
246        self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
247        self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
248        self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
249        self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
250        self.brushStyleComboBox.addItem("None", Qt.NoBrush)
251
252        brushStyleLabel = QLabel("&Brush Style:")
253        brushStyleLabel.setBuddy(self.brushStyleComboBox)
254
255        otherOptionsLabel = QLabel("Other Options:")
256        self.antialiasingCheckBox = QCheckBox("&Antialiasing")
257        self.transformationsCheckBox = QCheckBox("&Transformations")
258
259        self.shapeComboBox.activated.connect(self.shapeChanged)
260        self.penWidthSpinBox.valueChanged.connect(self.penChanged)
261        self.penStyleComboBox.activated.connect(self.penChanged)
262        self.penCapComboBox.activated.connect(self.penChanged)
263        self.penJoinComboBox.activated.connect(self.penChanged)
264        self.brushStyleComboBox.activated.connect(self.brushChanged)
265        self.antialiasingCheckBox.toggled.connect(self.renderArea.setAntialiased)
266        self.transformationsCheckBox.toggled.connect(self.renderArea.setTransformed)
267
268        mainLayout = QGridLayout()
269        mainLayout.setColumnStretch(0, 1)
270        mainLayout.setColumnStretch(3, 1)
271        mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
272        mainLayout.setRowMinimumHeight(1, 6)
273        mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
274        mainLayout.addWidget(self.shapeComboBox, 2, 2)
275        mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
276        mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
277        mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
278        mainLayout.addWidget(self.penStyleComboBox, 4, 2)
279        mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
280        mainLayout.addWidget(self.penCapComboBox, 5, 2)
281        mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
282        mainLayout.addWidget(self.penJoinComboBox, 6, 2)
283        mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
284        mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
285        mainLayout.setRowMinimumHeight(8, 6)
286        mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
287        mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
288        mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
289        self.setLayout(mainLayout)
290
291        self.shapeChanged()
292        self.penChanged()
293        self.brushChanged()
294        self.antialiasingCheckBox.setChecked(True)
295
296        self.setWindowTitle("Basic Drawing")
297
298    def shapeChanged(self):
299        shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
300                IdRole)
301        self.renderArea.setShape(shape)
302
303    def penChanged(self):
304        width = self.penWidthSpinBox.value()
305        style = Qt.PenStyle(self.penStyleComboBox.itemData(
306                self.penStyleComboBox.currentIndex(), IdRole))
307        cap = Qt.PenCapStyle(self.penCapComboBox.itemData(
308                self.penCapComboBox.currentIndex(), IdRole))
309        join = Qt.PenJoinStyle(self.penJoinComboBox.itemData(
310                self.penJoinComboBox.currentIndex(), IdRole))
311
312        self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))
313
314    def brushChanged(self):
315        style = Qt.BrushStyle(self.brushStyleComboBox.itemData(
316                self.brushStyleComboBox.currentIndex(), IdRole))
317
318        if style == Qt.LinearGradientPattern:
319            linearGradient = QLinearGradient(0, 0, 100, 100)
320            linearGradient.setColorAt(0.0, Qt.white)
321            linearGradient.setColorAt(0.2, Qt.green)
322            linearGradient.setColorAt(1.0, Qt.black)
323            self.renderArea.setBrush(QBrush(linearGradient))
324        elif style == Qt.RadialGradientPattern:
325            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
326            radialGradient.setColorAt(0.0, Qt.white)
327            radialGradient.setColorAt(0.2, Qt.green)
328            radialGradient.setColorAt(1.0, Qt.black)
329            self.renderArea.setBrush(QBrush(radialGradient))
330        elif style == Qt.ConicalGradientPattern:
331            conicalGradient = QConicalGradient(50, 50, 150)
332            conicalGradient.setColorAt(0.0, Qt.white)
333            conicalGradient.setColorAt(0.2, Qt.green)
334            conicalGradient.setColorAt(1.0, Qt.black)
335            self.renderArea.setBrush(QBrush(conicalGradient))
336        elif style == Qt.TexturePattern:
337            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
338        else:
339            self.renderArea.setBrush(QBrush(Qt.green, style))
340
341
342if __name__ == '__main__':
343
344    import sys
345
346    app = QApplication(sys.argv)
347    window = Window()
348    window.show()
349    sys.exit(app.exec_())
350