|
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 widgets/tooltips |
|
44 \title Tool Tips Example |
|
45 |
|
46 The Tool Tips example shows how to provide static and dynamic tool |
|
47 tips for an application's widgets. |
|
48 |
|
49 The simplest and most common way to set a widget's tool tip is by |
|
50 calling its QWidget::setToolTip() function (static tool |
|
51 tips). Then the tool tip is shown whenever the cursor points at |
|
52 the widget. We show how to do this with our application's tool |
|
53 buttons. But it is also possible to show different tool tips |
|
54 depending on the cursor's position (dynamic tooltips). This |
|
55 approach uses mouse tracking and event handling to determine what |
|
56 widgets are located under the cursor at any point in time, and |
|
57 displays their tool tips. The tool tips for the shape items in our |
|
58 application are implemented using the latter approach. |
|
59 |
|
60 \image tooltips-example.png |
|
61 |
|
62 With the \c Tooltips application the user can create new shape |
|
63 items with the provided tool buttons, and move the items around |
|
64 using the mouse. Tooltips are provided whenever the cursor is |
|
65 pointing to a shape item or one of the buttons. |
|
66 |
|
67 The Tooltips example consists of two classes: |
|
68 |
|
69 \list |
|
70 \o \c ShapeItem is a custom widget representing one single shape item. |
|
71 \o \c SortingBox inherits from QWidget and is the application's main |
|
72 widget. |
|
73 \endlist |
|
74 |
|
75 First we will review the \c SortingBox class, then we will take a |
|
76 look at the \c ShapeItem class. |
|
77 |
|
78 \section1 SortingBox Class Definition |
|
79 |
|
80 \snippet examples/widgets/tooltips/sortingbox.h 0 |
|
81 |
|
82 The \c SortingBox class inherits QWidget, and it is the Tooltips |
|
83 application's main widget. We reimplement several of the event |
|
84 handlers. |
|
85 |
|
86 The \c event() function provides tooltips, the \c resize() |
|
87 function makes sure the application appears consistently when the |
|
88 user resizes the main widget, and the \c paintEvent() function |
|
89 displays the shape items within the \c SortingBox widget. The |
|
90 mouse event handlers are reimplemented to make the user able to |
|
91 move the items around. |
|
92 |
|
93 In addition we need three private slots to make the user able to |
|
94 create new shape items. |
|
95 |
|
96 \snippet examples/widgets/tooltips/sortingbox.h 1 |
|
97 |
|
98 We also create several private functions: We use the \c |
|
99 initialItemPosition(), \c initialItemColor() and \c |
|
100 createToolButton() functions when we are constructing the widget, |
|
101 and we use the \c updateButtonGeometry() function whenever the |
|
102 user is resizing the application's main widget. |
|
103 |
|
104 The \c itemAt() function determines if there is a shape item at a |
|
105 particular position, and the \c moveItemTo() function moves an |
|
106 item to a new position. We use the \c createShapeItem(), \c |
|
107 randomItemPosition() and \c randomItemColor() functions to create |
|
108 new shape items. |
|
109 |
|
110 \snippet examples/widgets/tooltips/sortingbox.h 2 |
|
111 |
|
112 We keep all the shape items in a QList, and we keep three |
|
113 QPainterPath objects holding the shapes of a circle, a square and |
|
114 a triangle. We also need to have a pointer to an item when it is |
|
115 moving, and we need to know its previous position. |
|
116 |
|
117 \section1 SortingBox Class Implementation |
|
118 |
|
119 \snippet examples/widgets/tooltips/sortingbox.cpp 0 |
|
120 |
|
121 In the constructor, we first set the Qt::WA_StaticContents |
|
122 attribute on the widget. This attribute indicates that the widget |
|
123 contents are north-west aligned and static. On resize, such a |
|
124 widget will receive paint events only for the newly visible part |
|
125 of itself. |
|
126 |
|
127 \snippet examples/widgets/tooltips/sortingbox.cpp 1 |
|
128 |
|
129 To be able to show the appropiate tooltips while the user is |
|
130 moving the cursor around, we need to enable mouse tracking for the |
|
131 widget. |
|
132 |
|
133 If mouse tracking is disabled (the default), the widget only |
|
134 receives mouse move events when at least one mouse button is |
|
135 pressed while the mouse is being moved. If mouse tracking is |
|
136 enabled, the widget receives mouse move events even if no buttons |
|
137 are pressed. |
|
138 |
|
139 \snippet examples/widgets/tooltips/sortingbox.cpp 2 |
|
140 |
|
141 A widget's background role defines the brush from the widget's |
|
142 palette that is used to render the background, and QPalette::Base |
|
143 is typically white. |
|
144 |
|
145 \snippet examples/widgets/tooltips/sortingbox.cpp 3 |
|
146 |
|
147 After creating the application's tool buttons using the private \c |
|
148 createToolButton() function, we construct the shapes of a circle, |
|
149 a square and a triangle using QPainterPath. |
|
150 |
|
151 The QPainterPath class provides a container for painting |
|
152 operations, enabling graphical shapes to be constructed and |
|
153 reused. The main advantage of painter paths over normal drawing |
|
154 operations is that complex shapes only need to be created once, |
|
155 but they can be drawn many times using only calls to |
|
156 QPainter::drawPath(). |
|
157 |
|
158 \snippet examples/widgets/tooltips/sortingbox.cpp 4 |
|
159 |
|
160 Then we set the window title, resize the widget to a suitable |
|
161 size, and finally create three initial shape items using the |
|
162 private \c createShapeItem(), \c initialItemPosition() and \c |
|
163 initialItemColor() functions. |
|
164 |
|
165 \snippet examples/widgets/tooltips/sortingbox.cpp 5 |
|
166 |
|
167 QWidget::event() is the main event handler and receives all the |
|
168 widget's events. Normally, we recommend reimplementing one of the |
|
169 specialized event handlers instead of this function. But here we |
|
170 want to catch the QEvent::ToolTip events, and since these are |
|
171 rather rare, there exists no specific event handler. For that |
|
172 reason we reimplement the main event handler, and the first thing |
|
173 we need to do is to determine the event's type: |
|
174 |
|
175 \snippet examples/widgets/tooltips/sortingbox.cpp 6 |
|
176 |
|
177 If the type is QEvent::ToolTip, we cast the event to a QHelpEvent, |
|
178 otherwise we propagate the event using the QWidget::event() |
|
179 function. |
|
180 |
|
181 The QHelpEvent class provides an event that is used to request |
|
182 helpful information about a particular point in a widget. |
|
183 |
|
184 For example, the QHelpEvent::pos() function returns the event's |
|
185 position relative to the widget to which the event is dispatched. |
|
186 Here we use this information to determine if the position of the |
|
187 event is contained within the area of any of the shape items. If |
|
188 it is, we display the shape item's tooltip at the position of the |
|
189 event. If not, we hide the tooltip and explicitly ignore the event. |
|
190 This makes sure that the calling code does not start any tooltip |
|
191 specific modes as a result of the event. Note that the |
|
192 QToolTip::showText() function needs the event's position in global |
|
193 coordinates provided by QHelpEvent::globalPos(). |
|
194 |
|
195 \snippet examples/widgets/tooltips/sortingbox.cpp 7 |
|
196 |
|
197 The \c resizeEvent() function is reimplemented to receive the |
|
198 resize events dispatched to the widget. It makes sure that the |
|
199 tool buttons keep their position relative to the main widget when |
|
200 the widget is resized. We want the buttons to always be vertically |
|
201 aligned in the application's bottom right corner, so each time the |
|
202 main widget is resized we update the buttons geometry. |
|
203 |
|
204 \snippet examples/widgets/tooltips/sortingbox.cpp 8 |
|
205 |
|
206 The \c paintEvent() function is reimplemented to receive paint |
|
207 events for the widget. We create a QPainter for the \c SortingBox |
|
208 widget, and run through the list of created shape items, drawing |
|
209 each item at its defined position. |
|
210 |
|
211 \snippet examples/widgets/tooltips/sortingbox.cpp 9 |
|
212 |
|
213 The painter will by default draw all the shape items at position |
|
214 (0,0) in the \c SortingBox widget. The QPainter::translate() |
|
215 function translates the coordinate system by the given offset, |
|
216 making each shape item appear at its defined position. But |
|
217 remember to translate the coordinate system back when the item is |
|
218 drawn, otherwise the next shape item will appear at a position |
|
219 relative to the item we drawed last. |
|
220 |
|
221 \snippet examples/widgets/tooltips/sortingbox.cpp 10 |
|
222 |
|
223 The QPainter::setBrush() function sets the current brush used by |
|
224 the painter. When the provided argument is a QColor, the function |
|
225 calls the appropiate QBrush constructor which creates a brush with |
|
226 the specified color and Qt::SolidPattern style. The |
|
227 QPainter::drawPath() function draws the given path using the |
|
228 current pen for outline and the current brush for filling. |
|
229 |
|
230 \snippet examples/widgets/tooltips/sortingbox.cpp 11 |
|
231 |
|
232 The \c mousePressEvent() function is reimplemented to receive the |
|
233 mouse press events dispatched to the widget. It determines if an |
|
234 event's position is contained within the area of any of the shape |
|
235 items, using the private \c itemAt() function. |
|
236 |
|
237 If an item covers the position, we store a pointer to that item |
|
238 and the event's position. If several of the shape items cover the |
|
239 position, we store the pointer to the uppermost item. Finally, we |
|
240 move the shape item to the end of the list, and make a call to the |
|
241 QWidget::update() function to make the item appear on top. |
|
242 |
|
243 The QWidget::update() function does not cause an immediate |
|
244 repaint; instead it schedules a paint event for processing when Qt |
|
245 returns to the main event loop. |
|
246 |
|
247 \snippet examples/widgets/tooltips/sortingbox.cpp 12 |
|
248 |
|
249 The \c mouseMoveEvent() function is reimplemented to receive mouse |
|
250 move events for the widget. If the left mouse button is pressed |
|
251 and there exists a shape item in motion, we use the private \c |
|
252 moveItemTo() function to move the item with an offset |
|
253 corresponding to the offset between the positions of the current |
|
254 mouse event and the previous one. |
|
255 |
|
256 \snippet examples/widgets/tooltips/sortingbox.cpp 13 |
|
257 |
|
258 The \c mouseReleaseEvent() function is reimplemented to receive |
|
259 the mouse release events dispatched to the widget. If the left |
|
260 mouse button is pressed and there exists a shape item in motion, |
|
261 we use the private \c moveItemTo() function to move the item like |
|
262 we did in \c mouseMoveEvent(). But then we remove the pointer to |
|
263 the item in motion, making the shape item's position final for |
|
264 now. To move the item further, the user will need to press the |
|
265 left mouse button again. |
|
266 |
|
267 \snippet examples/widgets/tooltips/sortingbox.cpp 14 |
|
268 \codeline |
|
269 \snippet examples/widgets/tooltips/sortingbox.cpp 15 |
|
270 \codeline |
|
271 \snippet examples/widgets/tooltips/sortingbox.cpp 16 |
|
272 |
|
273 The \c createNewCircle(), \c createNewSquare() and \c |
|
274 createNewTriangle() slots simply create new shape items, using the |
|
275 private \c createShapeItem(), \c randomItemPosition() and \c |
|
276 randomItemColor() functions. |
|
277 |
|
278 \snippet examples/widgets/tooltips/sortingbox.cpp 17 |
|
279 |
|
280 In the \c itemAt() function, we run through the list of created |
|
281 shape items to check if the given position is contained within the |
|
282 area of any of the shape items. |
|
283 |
|
284 For each shape item we use the QPainterPath::contains() function |
|
285 to find out if the item's painter path contains the position. If |
|
286 it does we return the index of the item, otherwise we return |
|
287 -1. We run through the list backwards to get the index of the |
|
288 uppermost shape item in case several items cover the position. |
|
289 |
|
290 \snippet examples/widgets/tooltips/sortingbox.cpp 18 |
|
291 |
|
292 The \c moveItemTo() function moves the shape item in motion, and |
|
293 the parameter \c pos is the position of a mouse event. First we |
|
294 calculate the offset between the parameter \c pos and the previous |
|
295 mouse event position. Then we add the offset to the current |
|
296 position of the item in motion. |
|
297 |
|
298 It is tempting to simply set the position of the item to be the |
|
299 parameter \c pos. But an item's position defines the top left |
|
300 corner of the item's bounding rectangle, and the parameter \c pos |
|
301 can be any point; The suggested shortcut would cause the item to |
|
302 jump to a position where the cursor is pointing to the bounding |
|
303 rectangle's top left corner, regardless of the item's previous |
|
304 position. |
|
305 |
|
306 \snippet examples/widgets/tooltips/sortingbox.cpp 19 |
|
307 |
|
308 Finally, we update the previous mouse event position, and make a |
|
309 call to the QWidget::update() function to make the item appear at |
|
310 its new position. |
|
311 |
|
312 \snippet examples/widgets/tooltips/sortingbox.cpp 20 |
|
313 |
|
314 In the \c updateButtonGeometry() function we set the geometry for |
|
315 the given button. The parameter coordinates define the bottom |
|
316 right corner of the button. We use these coordinates and the |
|
317 button's size hint to determine the position of the upper left |
|
318 corner. This position, and the button's width and height, are the |
|
319 arguments required by the QWidget::setGeometry() function. |
|
320 |
|
321 In the end, we calculate and return the y-coordinate of the bottom |
|
322 right corner of the next button. We use the QWidget::style() |
|
323 function to retrieve the widget's GUI style, and then |
|
324 QStyle::pixelMetric() to determine the widget's preferred default |
|
325 spacing between its child widgets. |
|
326 |
|
327 \snippet examples/widgets/tooltips/sortingbox.cpp 21 |
|
328 |
|
329 The \c createShapeItem() function creates a single shape item. It |
|
330 sets the path, tooltip, position and color, using the item's own |
|
331 functions. In the end, the function appends the new item to the |
|
332 list of shape items, and calls the QWidget::update() function to |
|
333 make it appear with the other items within the \c SortingBox |
|
334 widget. |
|
335 |
|
336 \snippet examples/widgets/tooltips/sortingbox.cpp 22 |
|
337 |
|
338 The \c createToolButton() function is called from the \c |
|
339 SortingBox constructor. We create a tool button with the given |
|
340 tooltip and icon. The button's parent is the \c SortingBox widget, |
|
341 and its size is 32 x 32 pixels. Before we return the button, we |
|
342 connect it to the given slot. |
|
343 |
|
344 \snippet examples/widgets/tooltips/sortingbox.cpp 23 |
|
345 |
|
346 The \c initialItemPosition() function is also called from the |
|
347 constructor. We want the three first items to initially be |
|
348 centered in the middle of the \c SortingBox widget, and we use |
|
349 this function to calculate their positions. |
|
350 |
|
351 \snippet examples/widgets/tooltips/sortingbox.cpp 24 |
|
352 |
|
353 Whenever the user creates a new shape item, we want the new item |
|
354 to appear at a random position, and we use the \c |
|
355 randomItemPosition() function to calculate such a position. We |
|
356 make sure that the item appears within the visible area of the |
|
357 \c SortingBox widget, using the widget's current width and heigth |
|
358 when calculating the random coordinates. |
|
359 |
|
360 \snippet examples/widgets/tooltips/sortingbox.cpp 25 |
|
361 |
|
362 As with \c initialItemPosition(), the \c initialItemColor() |
|
363 function is called from the constructor. The purposes of both |
|
364 functions are purely cosmetic: We want to control the inital |
|
365 position and color of the three first items. |
|
366 |
|
367 \snippet examples/widgets/tooltips/sortingbox.cpp 26 |
|
368 |
|
369 Finally the \c randomItemColor() function is implemented to give |
|
370 the shape items the user creates, a random color. |
|
371 |
|
372 \section1 ShapeItem Class Definition |
|
373 |
|
374 \snippet examples/widgets/tooltips/shapeitem.h 0 |
|
375 |
|
376 The \c ShapeItem class is a custom widget representing one single |
|
377 shape item. The widget has a path, a position, a color and a |
|
378 tooltip. We need functions to set or modify these objects, as well |
|
379 as functions that return them. We make the latter functions \c |
|
380 const to prohibit any modifications of the objects, |
|
381 i.e. prohibiting unauthorized manipulation of the shape items |
|
382 appearance. |
|
383 |
|
384 \section1 ShapeItem Class Implementation |
|
385 |
|
386 \snippet examples/widgets/tooltips/shapeitem.cpp 0 |
|
387 \codeline |
|
388 \snippet examples/widgets/tooltips/shapeitem.cpp 1 |
|
389 \codeline |
|
390 \snippet examples/widgets/tooltips/shapeitem.cpp 2 |
|
391 \codeline |
|
392 \snippet examples/widgets/tooltips/shapeitem.cpp 3 |
|
393 |
|
394 This first group of functions simply return the objects that are |
|
395 requested. The objects are returned as constants, i.e. they cannot |
|
396 be modified. |
|
397 |
|
398 \snippet examples/widgets/tooltips/shapeitem.cpp 4 |
|
399 \codeline |
|
400 \snippet examples/widgets/tooltips/shapeitem.cpp 5 |
|
401 \codeline |
|
402 \snippet examples/widgets/tooltips/shapeitem.cpp 6 |
|
403 \codeline |
|
404 \snippet examples/widgets/tooltips/shapeitem.cpp 7 |
|
405 |
|
406 The last group of functions set or modify the shape item's path, |
|
407 position, color and tooltip, respectively. |
|
408 */ |