Update copyright headers
[qt:qt.git] / doc / src / examples / basicdrawing.qdoc
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the documentation of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:FDL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Free Documentation License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Free
19 ** Documentation License version 1.3 as published by the Free Software
20 ** Foundation and appearing in the file included in the packaging of
21 ** this file.  Please review the following information to ensure
22 ** the GNU Free Documentation License version 1.3 requirements
23 ** will be met: http://www.gnu.org/copyleft/fdl.html.
24 ** $QT_END_LICENSE$
25 **
26 ****************************************************************************/
27
28 /*!
29     \example painting/basicdrawing
30     \title Basic Drawing Example
31
32     \brief The Basic Drawing example shows how to display basic graphics
33     primitives in a variety of styles using the QPainter class.
34
35     QPainter performs low-level painting on widgets and other paint
36     devices. The class can draw everything from simple lines to
37     complex shapes like pies and chords. It can also draw aligned text
38     and pixmaps. Normally, it draws in a "natural" coordinate system,
39     but it can in addition do view and world transformation.
40
41     \image basicdrawing-example.png
42
43     The example provides a render area, displaying the currently
44     active shape, and lets the user manipulate the rendered shape and
45     its appearance using the QPainter parameters: The user can change
46     the active shape (\gui Shape), and modify the QPainter's pen (\gui
47     {Pen Width}, \gui {Pen Style}, \gui {Pen Cap}, \gui {Pen Join}),
48     brush (\gui {Brush Style}) and render hints (\gui
49     Antialiasing). In addition the user can rotate a shape (\gui
50     Transformations); behind the scenes we use QPainter's ability to
51     manipulate the coordinate system to perform the rotation.
52
53     The Basic Drawing example consists of two classes:
54
55     \list
56     \o \c RenderArea is a custom widget that renders multiple
57        copies of the currently active shape.
58     \o \c Window is the application's main window displaying a
59        \c RenderArea widget in addition to several parameter widgets.
60     \endlist
61
62     First we will review the \c Window class, then we will take a
63     look at the \c RenderArea class.
64
65     \section1 Window Class Definition
66
67     The Window class inherits QWidget, and is the application's main
68     window displaying a \c RenderArea widget in addition to several
69     parameter widgets.
70
71     \snippet examples/painting/basicdrawing/window.h 0
72
73     We declare the various widgets, and three private slots updating
74     the \c RenderArea widget: The \c shapeChanged() slot updates the
75     \c RenderArea widget when the user changes the currently active
76     shape. We call the \c penChanged() slot when either of the
77     QPainter's pen parameters changes. And the \c brushChanged() slot
78     updates the \c RenderArea widget when the user changes the
79     painter's brush style.
80
81     \section1 Window Class Implementation
82
83     In the constructor we create and initialize the various widgets
84     appearing in the main application window.
85
86     \snippet examples/painting/basicdrawing/window.cpp 1
87
88     First we create the \c RenderArea widget that will render the
89     currently active shape. Then we create the \gui Shape combobox,
90     and add the associated items (i.e. the different shapes a QPainter
91     can draw).
92
93     \snippet examples/painting/basicdrawing/window.cpp 2
94
95     QPainter's pen is a QPen object; the QPen class defines how a
96     painter should draw lines and outlines of shapes. A pen has
97     several properties: Width, style, cap and join.
98
99     A pen's width can be \e zero or greater, but the most common width
100     is zero. Note that this doesn't mean 0 pixels, but implies that
101     the shape is drawn as smoothly as possible although perhaps not
102     mathematically correct.
103
104     We create a QSpinBox for the \gui {Pen Width} parameter.
105
106     \snippet examples/painting/basicdrawing/window.cpp 3
107
108     The pen style defines the line type. The default style is solid
109     (Qt::SolidLine). Setting the style to none (Qt::NoPen) tells the
110     painter to not draw lines or outlines.  The pen cap defines how
111     the end points of lines are drawn.  And the pen join defines how
112     two lines join when multiple connected lines are drawn. The cap
113     and join only apply to lines with a width of 1 pixel or greater.
114
115     We create \l {QComboBox}es for each of the \gui {Pen Style}, \gui
116     {Pen Cap} and \gui {Pen Join} parameters, and adds the associated
117     items (i.e the values of the Qt::PenStyle, Qt::PenCapStyle and
118     Qt::PenJoinStyle enums respectively).
119
120     \snippet examples/painting/basicdrawing/window.cpp 4
121
122     The QBrush class defines the fill pattern of shapes drawn by a
123     QPainter. The default brush style is Qt::NoBrush. This style tells
124     the painter to not fill shapes. The standard style for filling is
125     Qt::SolidPattern.
126
127     We create a QComboBox for the \gui {Brush Style} parameter, and add
128     the associated items (i.e. the values of the Qt::BrushStyle enum).
129
130     \snippet examples/painting/basicdrawing/window.cpp 5
131     \snippet examples/painting/basicdrawing/window.cpp 6
132
133     Antialiasing is a feature that "smoothes" the pixels to create
134     more even and less jagged lines, and can be applied using
135     QPainter's render hints. QPainter::RenderHints are used to specify
136     flags to QPainter that may or may not be respected by any given
137     engine.
138
139     We simply create a QCheckBox for the \gui Antialiasing option.
140
141     \snippet examples/painting/basicdrawing/window.cpp 7
142
143     The \gui Transformations option implies a manipulation of the
144     coordinate system that will appear as if the rendered shape is
145     rotated in three dimensions.
146
147     We use the QPainter::translate(), QPainter::rotate() and
148     QPainter::scale() functions to implement this feature represented
149     in the main application window by a simple QCheckBox.
150
151     \snippet examples/painting/basicdrawing/window.cpp 8
152
153     Then we connect the parameter widgets with their associated slots
154     using the static QObject::connect() function, ensuring that the \c
155     RenderArea widget is updated whenever the user changes the shape,
156     or any of the other parameters.
157
158     \snippet examples/painting/basicdrawing/window.cpp 9
159     \snippet examples/painting/basicdrawing/window.cpp 10
160
161     Finally, we add the various widgets to a layout, and call the \c
162     shapeChanged(), \c penChanged(), and \c brushChanged() slots to
163     initialize the application. We also turn on antialiasing.
164
165     \snippet examples/painting/basicdrawing/window.cpp 11
166
167     The \c shapeChanged() slot is called whenever the user changes the
168     currently active shape.
169
170     First we retrieve the shape the user has chosen using the
171     QComboBox::itemData() function. This function returns the data for
172     the given role in the given index in the combobox. We use
173     QComboBox::currentIndex() to retrieve the index of the shape, and
174     the role is defined by the Qt::ItemDataRole enum; \c IdRole is an
175     alias for Qt::UserRole.
176
177     Note that Qt::UserRole is only the first role that can be used for
178     application-specific purposes. If you need to store different data
179     in the same index, you can use different roles by simply
180     incrementing the value of Qt::UserRole, for example: 'Qt::UserRole
181     + 1' and 'Qt::UserRole + 2'. However, it is a good programming
182     practice to give each role their own name: 'myFirstRole =
183     Qt::UserRole + 1' and 'mySecondRole = Qt::UserRole + 2'. Even
184     though we only need a single role in this particular example, we
185     add the following line of code to the beginning of the \c
186     window.cpp file.
187
188     \snippet examples/painting/basicdrawing/window.cpp 0
189
190     The QComboBox::itemData() function returns the data as a QVariant,
191     so we need to cast the data to \c RenderArea::Shape. If there is
192     no data for the given role, the function returns
193     QVariant::Invalid.
194
195     In the end we call the \c RenderArea::setShape() slot to update
196     the \c RenderArea widget.
197
198     \snippet examples/painting/basicdrawing/window.cpp 12
199
200     We call the \c penChanged() slot whenever the user changes any of
201     the pen parameters. Again we use the QComboBox::itemData()
202     function to retrieve the parameters, and then we call the \c
203     RenderArea::setPen() slot to update the \c RenderArea widget.
204
205     \snippet examples/painting/basicdrawing/window.cpp 13
206
207     The brushChanged() slot is called whenever the user changes the
208     brush parameter which we retrieve using the QComboBox::itemData()
209     function as before.
210
211     \snippet examples/painting/basicdrawing/window.cpp 14
212
213     If the brush parameter is a gradient fill, special actions are
214     required.
215
216     The QGradient class is used in combination with QBrush to specify
217     gradient fills. Qt currently supports three types of gradient
218     fills: linear, radial and conical. Each of these is represented by
219     a subclass of QGradient: QLinearGradient, QRadialGradient and
220     QConicalGradient.
221
222     So if the brush style is Qt::LinearGradientPattern, we first
223     create a QLinearGradient object with interpolation area between
224     the coordinates passed as arguments to the constructor. The
225     positions are specified using logical coordinates. Then we set the
226     gradient's colors using the QGradient::setColorAt() function. The
227     colors is defined using stop points which are composed by a
228     position (between 0 and 1) and a QColor. The set of stop points
229     describes how the gradient area should be filled. A gradient can
230     have an arbitrary number of stop points.
231
232     In the end we call \c RenderArea::setBrush() slot to update the \c
233     RenderArea widget's brush with the QLinearGradient object.
234
235     \snippet examples/painting/basicdrawing/window.cpp 15
236
237     A similar pattern of actions, as the one used for QLinearGradient,
238     is used in the cases of Qt::RadialGradientPattern and
239     Qt::ConicalGradientPattern.
240
241     The only difference is the arguments passed to the constructor:
242     Regarding the QRadialGradient constructor the first argument is
243     the center, and the second the radial gradient's radius. The third
244     argument is optional, but can be used to define the focal point of
245     the gradient inside the circle (the default focal point is the
246     circle center).  Regarding the QConicalGradient constructor, the
247     first argument specifies the center of the conical, and the second
248     specifies the start angle of the interpolation.
249
250     \snippet examples/painting/basicdrawing/window.cpp 16
251
252     If the brush style is Qt::TexturePattern we create a QBrush from a
253     QPixmap. Then we call \c RenderArea::setBrush() slot to update the
254     \c RenderArea widget with the newly created brush.
255
256     \snippet examples/painting/basicdrawing/window.cpp 17
257
258     Otherwise we simply create a brush with the given style and a
259     green color, and then call \c RenderArea::setBrush() slot to
260     update the \c RenderArea widget with the newly created brush.
261
262     \section1 RenderArea Class Definition
263
264     The \c RenderArea class inherits QWidget, and renders multiple
265     copies of the currently active shape using a QPainter.
266
267     \snippet examples/painting/basicdrawing/renderarea.h 0
268
269     First we define a public \c Shape enum to hold the different
270     shapes that can be rendered by the widget (i.e the shapes that can
271     be rendered by a QPainter). Then we reimplement the constructor as
272     well as two of QWidget's public functions: \l
273     {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l
274     {QWidget::sizeHint()}{sizeHint()}.
275
276     We also reimplement the QWidget::paintEvent() function to be able
277     to draw the currently active shape according to the specified
278     parameters.
279
280     We declare several private slots: The \c setShape() slot changes
281     the \c RenderArea's shape, the \c setPen() and \c setBrush() slots
282     modify the widget's pen and brush, and the \c setAntialiased() and
283     \c setTransformed() slots modify the widget's respective
284     properties.
285
286     \section1 RenderArea Class Implementation
287
288     In the constructor we initialize some of the widget's variables.
289
290     \snippet examples/painting/basicdrawing/renderarea.cpp 0
291
292     We set its shape to be a \gui Polygon, its antialiased property to
293     be false and we load an image into the widget's pixmap
294     variable. In the end we set the widget's background role, defining
295     the brush from the widget's \l {QWidget::palette}{palette} that
296     will be used to render the background. QPalette::Base is typically
297     white.
298
299     \snippet examples/painting/basicdrawing/renderarea.cpp 2
300
301     The \c RenderArea inherits QWidget's \l
302     {QWidget::sizeHint()}{sizeHint} property holding the recommended
303     size for the widget. If the value of this property is an invalid
304     size, no size is recommended.
305
306     The default implementation of the QWidget::sizeHint() function
307     returns an invalid size if there is no layout for the widget, and
308     returns the layout's preferred size otherwise.
309
310     Our reimplementation of the function returns a QSize with a 400
311     pixels width and a 200 pixels height.
312
313     \snippet examples/painting/basicdrawing/renderarea.cpp 1
314
315     \c RenderArea also inherits QWidget's
316     \l{QWidget::minimumSizeHint()}{minimumSizeHint} property holding
317     the recommended minimum size for the widget. Again, if the value
318     of this property is an invalid size, no size is recommended.
319
320     The default implementation of QWidget::minimumSizeHint() returns
321     an invalid size if there is no layout for the widget, and returns
322     the layout's minimum size otherwise.
323
324     Our reimplementation of the function returns a QSize with a 100
325     pixels width and a 100 pixels height.
326
327     \snippet examples/painting/basicdrawing/renderarea.cpp 3
328     \codeline
329     \snippet examples/painting/basicdrawing/renderarea.cpp 4
330     \codeline
331     \snippet examples/painting/basicdrawing/renderarea.cpp 5
332
333     The public \c setShape(), \c setPen() and \c setBrush() slots are
334     called whenever we want to modify a \c RenderArea widget's shape,
335     pen or brush. We set the shape, pen or brush according to the
336     slot parameter, and call QWidget::update() to make the changes
337     visible in the \c RenderArea widget.
338
339     The QWidget::update() slot does not cause an immediate
340     repaint; instead it schedules a paint event for processing when Qt
341     returns to the main event loop.
342
343     \snippet examples/painting/basicdrawing/renderarea.cpp 6
344     \codeline
345     \snippet examples/painting/basicdrawing/renderarea.cpp 7
346
347     With the \c setAntialiased() and \c setTransformed() slots we
348     change the state of the properties according to the slot
349     parameter, and call the QWidget::update() slot to make the changes
350     visible in the \c RenderArea widget.
351
352     \snippet examples/painting/basicdrawing/renderarea.cpp 8
353
354     Then we reimplement the QWidget::paintEvent() function. The first
355     thing we do is to create the graphical objects we will need to
356     draw the various shapes.
357
358     We create a vector of four \l {QPoint}s. We use this vector to
359     render the \gui Points, \gui Polyline and \gui Polygon
360     shapes. Then we create a QRect, defining a rectangle in the plane,
361     which we use as the bounding rectangle for all the shapes excluding
362     the \gui Path and the \gui Pixmap.
363
364     We also create a QPainterPath. The QPainterPath class provides a
365     container for painting operations, enabling graphical shapes to be
366     constructed and reused. A painter path is an object composed of a
367     number of graphical building blocks, such as rectangles, ellipses,
368     lines, and curves. For more information about the QPainterPath
369     class, see the \l {painting/painterpaths}{Painter Paths}
370     example. In this example, we create a painter path composed of one
371     straight line and a Bezier curve.
372
373     In addition we define a start angle and an arc length that we will
374     use when drawing the \gui Arc, \gui Chord and \gui Pie shapes.
375
376     \snippet examples/painting/basicdrawing/renderarea.cpp 9
377
378     We create a QPainter for the \c RenderArea widget, and set the
379     painters pen and brush according to the \c RenderArea's pen and
380     brush. If the \gui Antialiasing parameter option is checked, we
381     also set the painter's render hints. QPainter::Antialiasing
382     indicates that the engine should antialias edges of primitives if
383     possible.
384
385     \snippet examples/painting/basicdrawing/renderarea.cpp 10
386
387     Finally, we render the multiple copies of the \c RenderArea's
388     shape. The number of copies is depending on the size of the \c
389     RenderArea widget, and we calculate their positions using two \c
390     for loops and the widgets height and width.
391
392     For each copy we first save the current painter state (pushes the
393     state onto a stack). Then we translate the coordinate system,
394     using the QPainter::translate() function, to the position
395     determined by the variables of the \c for loops. If we omit this
396     translation of the coordinate system all the copies of the shape
397     will be rendered on top of each other in the top left cormer of
398     the \c RenderArea widget.
399
400     \snippet examples/painting/basicdrawing/renderarea.cpp 11
401
402     If the \gui Transformations parameter option is checked, we do an
403     additional translation of the coordinate system before we rotate
404     the coordinate system 60 degrees clockwise using the
405     QPainter::rotate() function and scale it down in size using the
406     QPainter::scale() function. In the end we translate the coordinate
407     system back to where it was before we rotated and scaled it.
408
409     Now, when rendering the shape, it will appear as if it was rotated
410     in three dimensions.
411
412     \snippet examples/painting/basicdrawing/renderarea.cpp 12
413
414     Next, we identify the \c RenderArea's shape, and render it using
415     the associated QPainter drawing function:
416
417     \list
418         \o QPainter::drawLine(),
419         \o QPainter::drawPoints(),
420         \o QPainter::drawPolyline(),
421         \o QPainter::drawPolygon(),
422         \o QPainter::drawRect(),
423         \o QPainter::drawRoundedRect(),
424         \o QPainter::drawEllipse(),
425         \o QPainter::drawArc(),
426         \o QPainter::drawChord(),
427         \o QPainter::drawPie(),
428         \o QPainter::drawPath(),
429         \o QPainter::drawText() or
430         \o QPainter::drawPixmap()
431     \endlist
432
433     Before we started rendering, we saved the current painter state
434     (pushes the state onto a stack). The rationale for this is that we
435     calculate each shape copy's position relative to the same point in
436     the coordinate system. When translating the coordinate system, we
437     lose the knowledge of this point unless we save the current
438     painter state \e before we start the translating process.
439
440     \snippet examples/painting/basicdrawing/renderarea.cpp 13
441
442     Then, when we are finished rendering a copy of the shape we can
443     restore the original painter state, with its associated coordinate
444     system, using the QPainter::restore() function. In this way we
445     ensure that the next shape copy will be rendered in the correct
446     position.
447
448     We could translate the coordinate system back using
449     QPainter::translate() instead of saving the painter state. But
450     since we in addition to translating the coordinate system (when
451     the \gui Transformation parameter option is checked) both rotate
452     and scale the coordinate system, the easiest solution is to save
453     the current painter state.
454 */