|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example opengl/2dpainting |
|
44 \title 2D Painting Example |
|
45 |
|
46 The 2D Painting example shows how QPainter and QGLWidget can be used |
|
47 together to display accelerated 2D graphics on supported hardware. |
|
48 |
|
49 \image 2dpainting-example.png |
|
50 |
|
51 The QPainter class is used to draw 2D graphics primitives onto |
|
52 paint devices provided by QPaintDevice subclasses, such as QWidget |
|
53 and QImage. |
|
54 |
|
55 Since QGLWidget is a subclass of QWidget, it is possible |
|
56 to reimplement its \l{QWidget::paintEvent()}{paintEvent()} and use |
|
57 QPainter to draw on the device, just as you would with a QWidget. |
|
58 The only difference is that the painting operations will be accelerated |
|
59 in hardware if it is supported by your system's OpenGL drivers. |
|
60 |
|
61 In this example, we perform the same painting operations on a |
|
62 QWidget and a QGLWidget. The QWidget is shown with anti-aliasing |
|
63 enabled, and the QGLWidget will also use anti-aliasing if the |
|
64 required extensions are supported by your system's OpenGL driver. |
|
65 |
|
66 \section1 Overview |
|
67 |
|
68 To be able to compare the results of painting onto a QGLWidget subclass |
|
69 with native drawing in a QWidget subclass, we want to show both kinds |
|
70 of widget side by side. To do this, we derive subclasses of QWidget and |
|
71 QGLWidget, using a separate \c Helper class to perform the same painting |
|
72 operations for each, and lay them out in a top-level widget, itself |
|
73 provided a the \c Window class. |
|
74 |
|
75 \section1 Helper Class Definition |
|
76 |
|
77 In this example, the painting operations are performed by a helper class. |
|
78 We do this because we want the same painting operations to be performed |
|
79 for both our QWidget subclass and the QGLWidget subclass. |
|
80 |
|
81 The \c Helper class is minimal: |
|
82 |
|
83 \snippet examples/opengl/2dpainting/helper.h 0 |
|
84 |
|
85 Apart from the constructor, it only provides a \c paint() function to paint |
|
86 using a painter supplied by one of our widget subclasses. |
|
87 |
|
88 \section1 Helper Class Implementation |
|
89 |
|
90 The constructor of the class sets up the resources it needs to paint |
|
91 content onto a widget: |
|
92 |
|
93 \snippet examples/opengl/2dpainting/helper.cpp 0 |
|
94 |
|
95 The actual painting is performed in the \c paint() function. This takes |
|
96 a QPainter that has already been set up to paint onto a paint device |
|
97 (either a QWidget or a QGLWidget), a QPaintEvent that provides information |
|
98 about the region to be painted, and a measure of the elapsed time (in |
|
99 milliseconds) since the paint device was last updated. |
|
100 |
|
101 \snippet examples/opengl/2dpainting/helper.cpp 1 |
|
102 |
|
103 We begin painting by filling in the region contained in the paint event |
|
104 before translating the origin of the coordinate system so that the rest |
|
105 of the painting operations will be displaced towards the center of the |
|
106 paint device. |
|
107 |
|
108 We draw a spiral pattern of circles, using the elapsed time specified to |
|
109 animate them so that they appear to move outward and around the coordinate |
|
110 system's origin: |
|
111 |
|
112 \snippet examples/opengl/2dpainting/helper.cpp 2 |
|
113 |
|
114 Since the coordinate system is rotated many times during |
|
115 this process, we \l{QPainter::save()}{save()} the QPainter's state |
|
116 beforehand and \l{QPainter::restore()}{restore()} it afterwards. |
|
117 |
|
118 \snippet examples/opengl/2dpainting/helper.cpp 3 |
|
119 |
|
120 We draw some text at the origin to complete the effect. |
|
121 |
|
122 \section1 Widget Class Definition |
|
123 |
|
124 The \c Widget class provides a basic custom widget that we use to |
|
125 display the simple animation painted by the \c Helper class. |
|
126 |
|
127 \snippet examples/opengl/2dpainting/widget.h 0 |
|
128 |
|
129 Apart from the constructor, it only contains a |
|
130 \l{QWidget::paintEvent()}{paintEvent()} function, that lets us draw |
|
131 customized content, and a slot that is used to animate its contents. |
|
132 One member variable keeps track of the \c Helper that the widget uses |
|
133 to paint its contents, and the other records the elapsed time since |
|
134 it was last updated. |
|
135 |
|
136 \section1 Widget Class Implementation |
|
137 |
|
138 The constructor only initializes the member variables, storing the |
|
139 \c Helper object supplied and calling the base class's constructor, |
|
140 and enforces a fixed size for the widget: |
|
141 |
|
142 \snippet examples/opengl/2dpainting/widget.cpp 0 |
|
143 |
|
144 The \c animate() slot is called whenever a timer, which we define later, times |
|
145 out: |
|
146 |
|
147 \snippet examples/opengl/2dpainting/widget.cpp 1 |
|
148 |
|
149 Here, we determine the interval that has elapsed since the timer last |
|
150 timed out, and we add it to any existing value before repainting the |
|
151 widget. Since the animation used in the \c Helper class loops every second, |
|
152 we can use the modulo operator to ensure that the \c elapsed variable is |
|
153 always less than 1000. |
|
154 |
|
155 Since the \c Helper class does all of the actual painting, we only have |
|
156 to implement a paint event that sets up a QPainter for the widget and calls |
|
157 the helper's \c paint() function: |
|
158 |
|
159 \snippet examples/opengl/2dpainting/widget.cpp 2 |
|
160 |
|
161 \section1 GLWidget Class Definition |
|
162 |
|
163 The \c GLWidget class definition is basically the same as the \c Widget |
|
164 class except that it is derived from QGLWidget. |
|
165 |
|
166 \snippet examples/opengl/2dpainting/glwidget.h 0 |
|
167 |
|
168 Again, the member variables record the \c Helper used to paint the |
|
169 widget and the elapsed time since the previous update. |
|
170 |
|
171 \section1 GLWidget Class Implementation |
|
172 |
|
173 The constructor differs a little from the \c Widget class's constructor: |
|
174 |
|
175 \snippet examples/opengl/2dpainting/glwidget.cpp 0 |
|
176 |
|
177 As well as initializing the \c elapsed member variable and storing the |
|
178 \c Helper object used to paint the widget, the base class's constructor |
|
179 is called with the format that specifies the \l QGL::SampleBuffers flag. |
|
180 This enables anti-aliasing if it is supported by your system's OpenGL |
|
181 driver. |
|
182 |
|
183 The \c animate() slot is exactly the same as that provided by the \c Widget |
|
184 class: |
|
185 |
|
186 \snippet examples/opengl/2dpainting/glwidget.cpp 1 |
|
187 |
|
188 The \c paintEvent() is almost the same as that found in the \c Widget class: |
|
189 |
|
190 \snippet examples/opengl/2dpainting/glwidget.cpp 2 |
|
191 |
|
192 Since anti-aliasing will be enabled if available, we only need to set up |
|
193 a QPainter on the widget and call the helper's \c paint() function to display |
|
194 the widget's contents. |
|
195 |
|
196 \section1 Window Class Definition |
|
197 |
|
198 The \c Window class has a basic, minimal definition: |
|
199 |
|
200 \snippet examples/opengl/2dpainting/window.h 0 |
|
201 |
|
202 It contains a single \c Helper object that will be shared between all |
|
203 widgets. |
|
204 |
|
205 \section1 Window Class Implementation |
|
206 |
|
207 The constructor does all the work, creating a widget of each type and |
|
208 inserting them with labels into a layout: |
|
209 |
|
210 \snippet examples/opengl/2dpainting/window.cpp 0 |
|
211 |
|
212 A timer with a 50 millisecond time out is constructed for animation purposes, |
|
213 and connected to the \c animate() slots of the \c Widget and \c GLWidget objects. |
|
214 Once started, the widgets should be updated at around 20 frames per second. |
|
215 |
|
216 \section1 Running the Example |
|
217 |
|
218 The example shows the same painting operations performed at the same time |
|
219 in a \c Widget and a \c GLWidget. The quality and speed of rendering in the |
|
220 \c GLWidget depends on the level of support for multisampling and hardware |
|
221 acceleration that your system's OpenGL driver provides. If support for either |
|
222 of these is lacking, the driver may fall back on a software renderer that |
|
223 may trade quality for speed. |
|
224 */ |