|
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 graphicsview/diagramscene |
|
44 \title Diagram Scene Example |
|
45 |
|
46 This example shows use of Qt's graphics framework. |
|
47 |
|
48 \image diagramscene.png |
|
49 |
|
50 The Diagram Scene example is an application in which you can |
|
51 create a flowchart diagram. It is possible to add flowchart shapes |
|
52 and text and connect the shapes by arrows as shown in the image |
|
53 above. The shapes, arrows, and text can be given different |
|
54 colors, and it is possible to change the font, style, and |
|
55 underline of the text. |
|
56 |
|
57 The Qt graphics view framework is designed to manage and |
|
58 display custom 2D graphics items. The main classes of the |
|
59 framework are QGraphicsItem, QGraphicsScene and QGraphicsView. The |
|
60 graphics scene manages the items and provides a surface for them. |
|
61 QGraphicsView is a widget that is used to render a scene on the |
|
62 screen. See the \l{The Graphics View Framework}{overview document} |
|
63 for a more detailed description of the framework. |
|
64 |
|
65 In this example we show how to create such custom graphics |
|
66 scenes and items by implementing classes that inherit |
|
67 QGraphicsScene and QGraphicsItem. |
|
68 |
|
69 In particular we show how to: |
|
70 |
|
71 \list |
|
72 \o Create custom graphics items. |
|
73 \o Handle mouse events and movement of items. |
|
74 \o Implement a graphics scene that can manage our custom items. |
|
75 \o Custom painting of items. |
|
76 \o Create a movable and editable text item. |
|
77 \endlist |
|
78 |
|
79 The example consists of the following classes: |
|
80 \list |
|
81 \o \c MainWindow creates the widgets and display |
|
82 them in a QMainWindow. It also manages the interaction |
|
83 between the widgets and the graphics scene, view and |
|
84 items. |
|
85 \o \c DiagramItem inherits QGraphicsPolygonItem and |
|
86 represents a flowchart shape. |
|
87 \o \c TextDiagramItem inherits QGraphicsTextItem and |
|
88 represents text items in the diagram. The class adds |
|
89 support for moving the item with the mouse, which is not |
|
90 supported by QGraphicsTextItem. |
|
91 \o \c Arrow inherits QGraphicsLineItem and is an arrow |
|
92 that connect two DiagramItems. |
|
93 \o \c DiagramScene inherits QGraphicsDiagramScene and |
|
94 provides support for \c DiagramItem, \c Arrow and |
|
95 \c DiagramTextItem (In addition to the support already |
|
96 handled by QGraphicsScene). |
|
97 \endlist |
|
98 |
|
99 \section1 MainWindow Class Definition |
|
100 |
|
101 \snippet examples/graphicsview/diagramscene/mainwindow.h 0 |
|
102 |
|
103 The \c MainWindow class creates and lays out the widgets in a |
|
104 QMainWindow. The class forwards input from the widgets to the |
|
105 DiagramScene. It also updates its widgets when the diagram |
|
106 scene's text item changes, or a diagram item or a diagram text item |
|
107 is inserted into the scene. |
|
108 |
|
109 The class also deletes items from the scene and handles the |
|
110 z-ordering, which decides the order in which items are drawn when |
|
111 they overlap each other. |
|
112 |
|
113 \section1 MainWindow Class Implementation |
|
114 |
|
115 |
|
116 We start with a look at the constructor: |
|
117 |
|
118 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 0 |
|
119 |
|
120 In the constructor we call methods to create the widgets and |
|
121 layouts of the example before we create the diagram scene. |
|
122 The toolbars must be created after the scene as they connect |
|
123 to its signals. We then lay the widgets out in the window. |
|
124 |
|
125 We connect to the \c itemInserted() and \c textInserted() slots of |
|
126 the diagram scenes as we want to uncheck the buttons in the tool |
|
127 box when an item is inserted. When an item is selected in |
|
128 the scene we receive the \c itemSelected() signal. We use this to |
|
129 update the widgets that display font properties if the item |
|
130 selected is a \c DiagramTextItem. |
|
131 |
|
132 The \c createToolBox() function creates and lays out the widgets |
|
133 of the \c toolBox QToolBox. We will not examine it with a |
|
134 high level of detail as it does not deal with graphics framework |
|
135 specific functionality. Here is its implementation: |
|
136 |
|
137 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 21 |
|
138 |
|
139 This part of the function sets up the tabbed widget item that |
|
140 contains the flowchart shapes. An exclusive QButtonGroup always |
|
141 keeps one button checked; we want the group to allow all buttons |
|
142 to be unchecked. |
|
143 We still use a button group since we can associate user |
|
144 data, which we use to store the diagram type, with each button. |
|
145 The \c createCellWidget() function sets up the buttons in the |
|
146 tabbed widget item and is examined later. |
|
147 |
|
148 The buttons of the background tabbed widget item is set up in the |
|
149 same way, so we skip to the creation of the tool box: |
|
150 |
|
151 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 22 |
|
152 |
|
153 We set the preferred size of the toolbox as its maximum. This |
|
154 way, more space is given to the graphics view. |
|
155 |
|
156 Here is the \c createActions() function: |
|
157 |
|
158 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 23 |
|
159 |
|
160 We show an example of the creation of an action. The |
|
161 functionality the actions trigger is discussed in the slots we |
|
162 connect the actions to. You can see the \l{Application |
|
163 Example}{application example} if you need a high-level |
|
164 introduction to actions. |
|
165 |
|
166 The is the \c createMenus() function: |
|
167 |
|
168 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 24 |
|
169 |
|
170 We create the three menus' of the example. |
|
171 |
|
172 The \c createToolbars() function sets up the examples tool |
|
173 bars. The three \l{QToolButton}s in the \c colorToolBar, the \c |
|
174 fontColorToolButton, \c fillColorToolButton, and \c |
|
175 lineColorToolButton, are interesting as we create icons for them |
|
176 by drawing on a QPixmap with a QPainter. We show how the \c |
|
177 fillColorToolButton is created. This button lets the user select a |
|
178 color for the diagram items. |
|
179 |
|
180 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 25 |
|
181 \dots |
|
182 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 26 |
|
183 |
|
184 We set the menu of the tool button with |
|
185 \l{QToolButton::}{setMenu()}. We need the \c fillAction QAction |
|
186 object to always be pointing to the selected action of the menu. |
|
187 The menu is created with the \c createColorMenu() function and, as |
|
188 we shall see later, contains one menu item for each color that the |
|
189 items can have. When the user presses the button, which trigger |
|
190 the \l{QToolButton::}{clicked()} signal, we can set the color of |
|
191 the selected item to the color of \c fillAction. It is with \c |
|
192 createColorToolButtonIcon() we create the icon for the button. |
|
193 |
|
194 \dots |
|
195 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 27 |
|
196 |
|
197 Here is the \c createBackgroundCellWidget() function: |
|
198 |
|
199 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 28 |
|
200 |
|
201 This function creates \l{QWidget}s containing a tool button |
|
202 and a label. The widgets created with this function are used for |
|
203 the background tabbed widget item in the tool box. |
|
204 |
|
205 Here is the \c createCellWidget() function: |
|
206 |
|
207 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 29 |
|
208 |
|
209 This function returns a QWidget containing a QToolButton with |
|
210 an image of one of the \c DiagramItems, i.e., flowchart shapes. |
|
211 The image is created by the \c DiagramItem through the \c image() |
|
212 function. The QButtonGroup class lets us attach a QVariant with |
|
213 each button; we store the diagram's type, i.e., the |
|
214 DiagramItem::DiagramType enum. We use the stored diagram type when |
|
215 we create new diagram items for the scene. The widgets created |
|
216 with this function is used in the tool box. |
|
217 |
|
218 Here is the \c createColorMenu() function: |
|
219 |
|
220 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 30 |
|
221 |
|
222 This function creates a color menu that is used as the |
|
223 drop-down menu for the tool buttons in the \c colorToolBar. We |
|
224 create an action for each color that we add to the menu. We fetch |
|
225 the actions data when we set the color of items, lines, and text. |
|
226 |
|
227 Here is the \c createColorToolButtonIcon() function: |
|
228 |
|
229 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 31 |
|
230 |
|
231 This function is used to create the QIcon of the \c |
|
232 fillColorToolButton, \c fontColorToolButton, and \c |
|
233 lineColorToolButton. The \a imageFile string is either the text, |
|
234 flood-fill, or line symbol that is used for the buttons. Beneath |
|
235 the image we draw a filled rectangle using \a color. |
|
236 |
|
237 Here is the \c createColorIcon() function: |
|
238 |
|
239 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 32 |
|
240 |
|
241 This function creates an icon with a filled rectangle in the |
|
242 color of \a color. It is used for creating icons for the color |
|
243 menus in the \c fillColorToolButton, \c fontColorToolButton, and |
|
244 \c lineColorToolButton. |
|
245 |
|
246 Here is the \c backgroundButtonGroupClicked() slot: |
|
247 |
|
248 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 1 |
|
249 |
|
250 In this function we set the QBrush that is used to draw the |
|
251 background of the diagramscene. The background can be a grid of |
|
252 squares of blue, gray, or white tiles, or no grid at all. We have |
|
253 \l{QPixmap}s of the tiles from png files that we create the brush |
|
254 with. |
|
255 |
|
256 When one of the buttons in the background tabbed widget item is |
|
257 clicked we change the brush; we find out which button it is by |
|
258 checking its text. |
|
259 |
|
260 Here is the implementation of \c buttonGroupClicked(): |
|
261 |
|
262 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 2 |
|
263 |
|
264 This slot is called when a button in \c buttonGroup is checked. |
|
265 When a button is checked the user can click on the graphics view |
|
266 and a \c DiagramItem of the selected type will be inserted into |
|
267 the \c DiagramScene. We must loop through the buttons in the group |
|
268 to uncheck other buttons as only one button is allowed to be |
|
269 checked at a time. |
|
270 |
|
271 \c QButtonGroup assigns an id to each button. We have set the id |
|
272 of each button to the diagram type, as given by DiagramItem::DiagramType |
|
273 that will be inserted into the scene when it is clicked. We can |
|
274 then use the button id when we set the diagram type with |
|
275 \c setItemType(). In the case of text we assigned an id that has a |
|
276 value that is not in the DiagramType enum. |
|
277 |
|
278 Here is the implementation of \c deleteItem(): |
|
279 |
|
280 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 3 |
|
281 |
|
282 This slot deletes the selected item, if any, from the scene. If |
|
283 the item to be deleted is a \c DiagramItem, we also need to delete |
|
284 arrows connected to it; we don't want arrows in the scene that |
|
285 aren't connected to items in both ends. |
|
286 |
|
287 This is the implementation of pointerGroupClicked(): |
|
288 |
|
289 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 4 |
|
290 |
|
291 The \c pointerTypeGroup decides whether the scene is in ItemMove |
|
292 or InsertLine mode. This button group is exclusive, i.e., only |
|
293 one button is checked at any time. As with the \c buttonGroup above |
|
294 we have assigned an id to the buttons that matches values of the |
|
295 DiagramScene::Mode enum, so that we can use the id to set the |
|
296 correct mode. |
|
297 |
|
298 Here is the \c bringToFront() slot: |
|
299 |
|
300 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 5 |
|
301 |
|
302 Several items may collide, i.e., overlap, with each other in |
|
303 the scene. This slot is called when the user requests that an |
|
304 item should be placed on top of the items it collides with. |
|
305 \l{QGraphicsItem}{QGrapicsItems} have a z-value that decides the |
|
306 order in which items are stacked in the scene; you can think of it |
|
307 as the z-axis in a 3D coordinate system. When items collide the |
|
308 items with higher z-values will be drawn on top of items with |
|
309 lower values. When we bring an item to the front we can loop |
|
310 through the items it collides with and set a z-value that is |
|
311 higher than all of them. |
|
312 |
|
313 Here is the \c sendToBack() slot: |
|
314 |
|
315 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 6 |
|
316 |
|
317 This slot works in the same way as \c bringToFront() described |
|
318 above, but sets a z-value that is lower than items the item that |
|
319 should be send to the back collides with. |
|
320 |
|
321 This is the implementation of \c itemInserted(): |
|
322 |
|
323 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 7 |
|
324 |
|
325 This slot is called from the \c DiagramScene when an item has been |
|
326 added to the scene. We set the mode of the scene back to the mode |
|
327 before the item was inserted, which is ItemMove or InsertText |
|
328 depending on which button is checked in the \c pointerTypeGroup. |
|
329 We must also uncheck the button in the in the \c buttonGroup. |
|
330 |
|
331 Here is the implementation of \c textInserted(): |
|
332 |
|
333 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 8 |
|
334 |
|
335 We simply set the mode of the scene back to the mode it had before |
|
336 the text was inserted. |
|
337 |
|
338 Here is the \c currentFontChanged() slot: |
|
339 |
|
340 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 9 |
|
341 |
|
342 When the user requests a font change, by using one of the |
|
343 widgets in the \c fontToolBar, we create a new QFont object and |
|
344 set its properties to match the state of the widgets. This is done |
|
345 in \c handleFontChange(), so we simply call that slot. |
|
346 |
|
347 Here is the \c fontSizeChanged() slot: |
|
348 |
|
349 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 10 |
|
350 |
|
351 When the user requests a font change, by using one of the |
|
352 widgets in the \c fontToolBar, we create a new QFont object and |
|
353 set its properties to match the state of the widgets. This is done |
|
354 in \c handleFontChange(), so we simply call that slot. |
|
355 |
|
356 Here is the implementation of \c sceneScaleChanged(): |
|
357 |
|
358 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 11 |
|
359 |
|
360 The user can increase or decrease the scale, with the \c |
|
361 sceneScaleCombo, the scene is drawn in. |
|
362 It is not the scene itself that changes its scale, but only the |
|
363 view. |
|
364 |
|
365 Here is the \c textColorChanged() slot: |
|
366 |
|
367 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 12 |
|
368 |
|
369 This slot is called when an item in the drop-down menu of the \c |
|
370 fontColorToolButton is pressed. We need to change the icon on |
|
371 the button to the color of the selected QAction. We keep a pointer |
|
372 to the selected action in \c textAction. It is in \c |
|
373 textButtonTriggered() we change the text color to the color of \c |
|
374 textAction, so we call that slot. |
|
375 |
|
376 Here is the \c itemColorChanged() implementation: |
|
377 |
|
378 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 13 |
|
379 |
|
380 This slot handles requests for changing the color of \c |
|
381 DiagramItems in the same manner as \c textColorChanged() does for |
|
382 \c DiagramTextItems. |
|
383 |
|
384 Here is the implementation of \c lineColorChanged(): |
|
385 |
|
386 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 14 |
|
387 |
|
388 This slot handles requests for changing the color of \c Arrows in |
|
389 the same manner that \c textColorChanged() does it for \c |
|
390 DiagramTextItems. |
|
391 |
|
392 Here is the \c textButtonTriggered() slot: |
|
393 |
|
394 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 15 |
|
395 |
|
396 \c textAction points to the QAction of the currently selected menu item |
|
397 in the \c fontColorToolButton's color drop-down menu. We have set |
|
398 the data of the action to the QColor the action represents, so we |
|
399 can simply fetch this when we set the color of text with \c |
|
400 setTextColor(). |
|
401 |
|
402 Here is the \c fillButtonTriggered() slot: |
|
403 |
|
404 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 16 |
|
405 |
|
406 \c fillAction points to the selected menu item in the drop-down |
|
407 menu of \c fillColorToolButton(). We can therefore use the data of |
|
408 this action when we set the item color with \c setItemColor(). |
|
409 |
|
410 Here is the \c lineButtonTriggered() slot: |
|
411 |
|
412 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 17 |
|
413 |
|
414 \c lineAction point to the selected item in the drop-down menu of |
|
415 \c lineColorToolButton. We use its data when we set the arrow |
|
416 color with \c setLineColor(). |
|
417 |
|
418 Here is the \c handleFontChange() function: |
|
419 |
|
420 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 18 |
|
421 |
|
422 \c handleFontChange() is called when any of the widgets that show |
|
423 font properties changes. We create a new QFont object and set its |
|
424 properties based on the widgets. We then call the \c setFont() |
|
425 function of \c DiagramScene; it is the scene that set the font of |
|
426 the \c DiagramTextItems it manages. |
|
427 |
|
428 Here is the \c itemSelected() slot: |
|
429 |
|
430 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 19 |
|
431 |
|
432 This slot is called when an item in the \c DiagramScene is |
|
433 selected. In the case of this example it is only text items that |
|
434 emit signals when they are selected, so we do not need to check |
|
435 what kind of graphics \a item is. |
|
436 |
|
437 We set the state of the widgets to match the properties of the |
|
438 font of the selected text item. |
|
439 |
|
440 This is the \c about() slot: |
|
441 |
|
442 \snippet examples/graphicsview/diagramscene/mainwindow.cpp 20 |
|
443 |
|
444 This slot displays an about box for the example when the user |
|
445 selects the about menu item from the help menu. |
|
446 |
|
447 \section1 DiagramScene Class Definition |
|
448 |
|
449 The \c DiagramScene class inherits QGraphicsScene and adds |
|
450 functionality to handle \c DiagramItems, \c Arrows, and \c |
|
451 DiagramTextItems in addition to the items handled by its super |
|
452 class. |
|
453 |
|
454 |
|
455 \snippet examples/graphicsview/diagramscene/diagramscene.h 0 |
|
456 |
|
457 In the \c DiagramScene a mouse click can give three different |
|
458 actions: the item under the mouse can be moved, an item may be |
|
459 inserted, or an arrow may be connected between to diagram items. |
|
460 Which action a mouse click has depends on the mode, given by the |
|
461 Mode enum, the scene is in. The mode is set with the \c setMode() |
|
462 function. |
|
463 |
|
464 The scene also sets the color of its items and the font of its |
|
465 text items. The colors and font used by the scene can be set with |
|
466 the \c setLineColor(), \c setTextColor(), \c setItemColor() and \c |
|
467 setFont() functions. The type of \c DiagramItem, given by the |
|
468 DiagramItem::DiagramType function, to be created when an item is |
|
469 inserted is set with the \c setItemType() slot. |
|
470 |
|
471 The \c MainWindow and \c DiagramScene share responsibility for |
|
472 the examples functionality. \c MainWindow handles the following |
|
473 tasks: the deletion of items, text, and arrows; moving diagram |
|
474 items to the back and front; and setting the scale of the scene. |
|
475 |
|
476 \section1 DiagramScene Class Implementation |
|
477 |
|
478 |
|
479 We start with the constructor: |
|
480 |
|
481 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 0 |
|
482 |
|
483 The scene uses \c myItemMenu to set the context menu when it |
|
484 creates \c DiagramItems. We set the default mode to \c |
|
485 DiagramScene::MoveItem as this gives the default behavior of |
|
486 QGraphicsScene. |
|
487 |
|
488 Here is the \c setLineColor() function: |
|
489 |
|
490 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 1 |
|
491 |
|
492 The \c isItemChange function returns true if an \c Arrow item is |
|
493 selected in the scene in which case we want to change its color. |
|
494 When the \c DiagramScene creates and adds new arrows to the scene |
|
495 it will also use the new \a color. |
|
496 |
|
497 Here is the \c setTextColor() function: |
|
498 |
|
499 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 2 |
|
500 |
|
501 This function sets the color of \c DiagramTextItems equal to the |
|
502 way \c setLineColor() sets the color of \c Arrows. |
|
503 |
|
504 Here is the \c setItemColor() function: |
|
505 |
|
506 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 3 |
|
507 |
|
508 This function sets the color the scene will use when creating |
|
509 \c DiagramItems. It also changes the color of a selected \c |
|
510 DiagramItem. |
|
511 |
|
512 This is the implementation of \c setFont(): |
|
513 |
|
514 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 4 |
|
515 |
|
516 Set the font to use for new and selected, if a text item is |
|
517 selected, \c DiagramTextItems. |
|
518 |
|
519 This is the implementation of \c editorLostFocus() slot: |
|
520 |
|
521 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 5 |
|
522 |
|
523 \c DiagramTextItems emit a signal when they loose focus, which is |
|
524 connected to this slot. We remove the item if it has no text. |
|
525 If not, we would leak memory and confuse the user as the items |
|
526 will be edited when pressed on by the mouse. |
|
527 |
|
528 The \c mousePressEvent() function handles mouse press event's |
|
529 different depending on which mode the \c DiagramScene is in. We |
|
530 examine its implementation for each mode: |
|
531 |
|
532 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 6 |
|
533 |
|
534 We simply create a new \c DiagramItem and add it to the scene at |
|
535 the position the mouse was pressed. Note that the origin of its |
|
536 local coordinate system will be under the mouse pointer position. |
|
537 |
|
538 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 7 |
|
539 |
|
540 The user adds \c Arrows to the scene by stretching a line between |
|
541 the items the arrow should connect. The start of the line is fixed |
|
542 in the place the user clicked the mouse and the end follows the |
|
543 mouse pointer as long as the button is held down. When the user |
|
544 releases the mouse button an \c Arrow will be added to the scene |
|
545 if there is a \c DiagramItem under the start and end of the line. |
|
546 We will see how this is implemented later; here we simply add the |
|
547 line. |
|
548 |
|
549 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 8 |
|
550 |
|
551 The \c DiagramTextItem is editable when the |
|
552 Qt::TextEditorInteraction flag is set, else it is movable by the |
|
553 mouse. We always want the text to be drawn on top of the other |
|
554 items in the scene, so we set the value to a number higher |
|
555 than other items in the scene. |
|
556 |
|
557 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 9 |
|
558 |
|
559 We are in MoveItem mode if we get to the default switch; we |
|
560 can then call the QGraphicsScene implementation, which |
|
561 handles movement of items with the mouse. We make this call even |
|
562 if we are in another mode making it possible to add an item and |
|
563 then keep the mouse button pressed down and start moving |
|
564 the item. In the case of text items, this is not possible as they |
|
565 do not propagate mouse events when they are editable. |
|
566 |
|
567 This is the \c mouseMoveEvent() function: |
|
568 |
|
569 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 10 |
|
570 |
|
571 We must draw the line if we are in InsertMode and the mouse button |
|
572 is pressed down (the line is not 0). As discussed in \c |
|
573 mousePressEvent() the line is drawn from the position the mouse |
|
574 was pressed to the current position of the mouse. |
|
575 |
|
576 If we are in MoveItem mode, we call the QGraphicsScene |
|
577 implementation, which handles movement of items. |
|
578 |
|
579 In the \c mouseReleaseEvent() function we need to check if an arrow |
|
580 should be added to the scene: |
|
581 |
|
582 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 11 |
|
583 |
|
584 First we need to get the items (if any) under the line's start |
|
585 and end points. The line itself is the first item at these points, |
|
586 so we remove it from the lists. As a precaution, we check if the |
|
587 lists are empty, but this should never happen. |
|
588 |
|
589 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 12 |
|
590 |
|
591 Now we check if there are two different \c DiagramItems under |
|
592 the lines start and end points. If there are we can create an \c |
|
593 Arrow with the two items. The arrow is then added to each item and |
|
594 finally the scene. The arrow must be updated to adjust its start |
|
595 and end points to the items. We set the z-value of the arrow to |
|
596 -1000.0 because we always want it to be drawn under the items. |
|
597 |
|
598 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 13 |
|
599 |
|
600 Here is the \c isItemChange() function: |
|
601 |
|
602 \snippet examples/graphicsview/diagramscene/diagramscene.cpp 14 |
|
603 |
|
604 The scene has single selection, i.e., only one item can be |
|
605 selected at any given time. The foreach will then loop one time |
|
606 with the selected item or none if no item is selected. \c |
|
607 isItemChange() is used to check whether a selected item exists |
|
608 and also is of the specified diagram \a type. |
|
609 |
|
610 \section1 DiagramItem Class Definition |
|
611 |
|
612 |
|
613 \snippet examples/graphicsview/diagramscene/diagramitem.h 0 |
|
614 |
|
615 The \c DiagramItem represents a flowchart shape in the \c |
|
616 DiagramScene. It inherits QGraphicsPolygonItem and has a polygon |
|
617 for each shape. The enum DiagramType has a value for each of the |
|
618 flowchart shapes. |
|
619 |
|
620 The class has a list of the arrows that are connected to it. |
|
621 This is necessary because only the item knows when it is being |
|
622 moved (with the \c itemChanged() function) at which time the |
|
623 arrows must be updated. The item can also draw itself onto a |
|
624 QPixmap with the \c image() function. This is used for the tool |
|
625 buttons in \c MainWindow, see \c createColorToolButtonIcon() in |
|
626 \c MainWindow. |
|
627 |
|
628 The Type enum is a unique identifier of the class. It is used by |
|
629 \c qgraphicsitem_cast(), which does dynamic casts of graphics |
|
630 items. The UserType constant is the minimum value a custom |
|
631 graphics item type can be. |
|
632 |
|
633 \section1 DiagramItem Class Implementation |
|
634 |
|
635 |
|
636 We start with a look at the constructor: |
|
637 |
|
638 \snippet examples/graphicsview/diagramscene/diagramitem.cpp 0 |
|
639 |
|
640 In the constructor we create the items polygon according to |
|
641 \a diagramType. \l{QGraphicsItem}s are not movable or selectable |
|
642 by default, so we must set these properties. |
|
643 |
|
644 Here is the \c removeArrow() function: |
|
645 |
|
646 \snippet examples/graphicsview/diagramscene/diagramitem.cpp 1 |
|
647 |
|
648 \c removeArrow() is used to remove \c Arrow items when they |
|
649 or \c DiagramItems they are connected to are removed from the |
|
650 scene. |
|
651 |
|
652 Here is the \c removeArrows() function: |
|
653 |
|
654 \snippet examples/graphicsview/diagramscene/diagramitem.cpp 2 |
|
655 |
|
656 This function is called when the item is removed from the scene |
|
657 and removes all arrows that are connected to this item. The arrow |
|
658 must be removed from the \c arrows list of both its start and end |
|
659 item. |
|
660 |
|
661 Here is the \c addArrow() function: |
|
662 |
|
663 \snippet examples/graphicsview/diagramscene/diagramitem.cpp 3 |
|
664 |
|
665 This function simply adds the \a arrow to the items \c arrows list. |
|
666 |
|
667 Here is the \c image() function: |
|
668 |
|
669 \snippet examples/graphicsview/diagramscene/diagramitem.cpp 4 |
|
670 |
|
671 This function draws the polygon of the item onto a QPixmap. In |
|
672 this example we use this to create icons for the tool buttons in |
|
673 the tool box. |
|
674 |
|
675 Here is the \c contextMenuEvent() function: |
|
676 |
|
677 \snippet examples/graphicsview/diagramscene/diagramitem.cpp 5 |
|
678 |
|
679 We show the context menu. As right mouse clicks, which shows the |
|
680 menu, don't select items by default we set the item selected with |
|
681 \l{QGraphicsItem::}{setSelected()}. This is necessary since an |
|
682 item must be selected to change its elevation with the |
|
683 \c bringToFront and \c sendToBack actions. |
|
684 |
|
685 This is the implementation of \c itemChange(): |
|
686 |
|
687 \snippet examples/graphicsview/diagramscene/diagramitem.cpp 6 |
|
688 |
|
689 If the item has moved, we need to update the positions of the |
|
690 arrows connected to it. The implementation of QGraphicsItem does |
|
691 nothing, so we just return \a value. |
|
692 |
|
693 \section1 DiagramTextItem Class Definition |
|
694 |
|
695 The \c TextDiagramItem class inherits QGraphicsTextItem and |
|
696 adds the possibility to move editable text items. Editable |
|
697 QGraphicsTextItems are designed to be fixed in place and editing |
|
698 starts when the user single clicks on the item. With \c |
|
699 DiagramTextItem the editing starts with a double click leaving |
|
700 single click available to interact with and move it. |
|
701 |
|
702 \snippet examples/graphicsview/diagramscene/diagramtextitem.h 0 |
|
703 |
|
704 We use \c itemChange() and \c focusOutEvent() to notify the |
|
705 \c DiagramScene when the text item loses focus and gets selected. |
|
706 |
|
707 We reimplement the functions that handle mouse events to make it |
|
708 possible to alter the mouse behavior of QGraphicsTextItem. |
|
709 |
|
710 \section1 DiagramTextItem Implementation |
|
711 |
|
712 We start with the constructor: |
|
713 |
|
714 \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 0 |
|
715 |
|
716 We simply set the item movable and selectable, as these flags are |
|
717 off by default. |
|
718 |
|
719 Here is the \c itemChange() function: |
|
720 |
|
721 \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 1 |
|
722 |
|
723 When the item is selected we emit the selectedChanged signal. The |
|
724 \c MainWindow uses this signal to update the widgets that display |
|
725 font properties to the font of the selected text item. |
|
726 |
|
727 Here is the \c focusOutEvent() function: |
|
728 |
|
729 \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 2 |
|
730 |
|
731 \c DiagramScene uses the signal emitted when the text item looses |
|
732 focus to remove the item if it is empty, i.e., it contains no |
|
733 text. |
|
734 |
|
735 This is the implementation of \c mouseDoubleClickEvent(): |
|
736 |
|
737 \snippet examples/graphicsview/diagramscene/diagramtextitem.cpp 5 |
|
738 |
|
739 When we receive a double click event, we make the item editable by calling |
|
740 QGraphicsTextItem::setTextInteractionFlags(). We then forward the |
|
741 double-click to the item itself. |
|
742 |
|
743 \section1 Arrow Class Definition |
|
744 |
|
745 The \c Arrow class is a graphics item that connects two \c |
|
746 DiagramItems. It draws an arrow head to one of the items. To |
|
747 achieve this the item needs to paint itself and also re implement |
|
748 methods used by the graphics scene to check for collisions and |
|
749 selections. The class inherits QGraphicsLine item, and draws the |
|
750 arrowhead and moves with the items it connects. |
|
751 |
|
752 \snippet examples/graphicsview/diagramscene/arrow.h 0 |
|
753 |
|
754 The item's color can be set with \c setColor(). |
|
755 |
|
756 \c boundingRect() and \c shape() are reimplemented |
|
757 from QGraphicsLineItem and are used by the scene |
|
758 to check for collisions and selections. |
|
759 |
|
760 Calling \c updatePosition() causes the arrow to recalculate its |
|
761 position and arrow head angle. \c paint() is reimplemented so that |
|
762 we can paint an arrow rather than just a line between items. |
|
763 |
|
764 \c myStartItem and \c myEndItem are the diagram items that the |
|
765 arrow connects. The arrow is drawn with its head to the end item. |
|
766 \c arrowHead is a polygon with three vertices's we use to draw the |
|
767 arrow head. |
|
768 |
|
769 \section1 Arrow Class Implementation |
|
770 |
|
771 The constructor of the \c Arrow class looks like this: |
|
772 |
|
773 \snippet examples/graphicsview/diagramscene/arrow.cpp 0 |
|
774 |
|
775 We set the start and end diagram items of the arrow. The arrow |
|
776 head will be drawn where the line intersects the end item. |
|
777 |
|
778 Here is the \c boundingRect() function: |
|
779 |
|
780 \snippet examples/graphicsview/diagramscene/arrow.cpp 1 |
|
781 |
|
782 We need to reimplement this function because the arrow is |
|
783 larger than the bounding rectangle of the QGraphicsLineItem. The |
|
784 graphics scene uses the bounding rectangle to know which regions |
|
785 of the scene to update. |
|
786 |
|
787 Here is the \c shape() function: |
|
788 |
|
789 \snippet examples/graphicsview/diagramscene/arrow.cpp 2 |
|
790 |
|
791 The shape function returns a QPainterPath that is the exact |
|
792 shape of the item. The QGraphicsLineItem::shape() returns a path |
|
793 with a line drawn with the current pen, so we only need to add |
|
794 the arrow head. This function is used to check for collisions and |
|
795 selections with the mouse. |
|
796 |
|
797 Here is the \c updatePosition() slot: |
|
798 |
|
799 \snippet examples/graphicsview/diagramscene/arrow.cpp 3 |
|
800 |
|
801 This slot updates the arrow by setting the start and end |
|
802 points of its line to the center of the items it connects. |
|
803 |
|
804 Here is the \c paint() function: |
|
805 |
|
806 \snippet examples/graphicsview/diagramscene/arrow.cpp 4 |
|
807 |
|
808 If the start and end items collide we do not draw the arrow; the |
|
809 algorithm we use to find the point the arrow should be drawn at |
|
810 may fail if the items collide. |
|
811 |
|
812 We first set the pen and brush we will use for drawing the arrow. |
|
813 |
|
814 \snippet examples/graphicsview/diagramscene/arrow.cpp 5 |
|
815 |
|
816 We then need to find the position at which to draw the |
|
817 arrowhead. The head should be drawn where the line and the end |
|
818 item intersects. This is done by taking the line between each |
|
819 point in the polygon and check if it intersects with the line of |
|
820 the arrow. Since the line start and end points are set to the |
|
821 center of the items the arrow line should intersect one and only |
|
822 one of the lines of the polygon. Note that the points in the |
|
823 polygon are relative to the local coordinate system of the item. |
|
824 We must therefore add the position of the end item to make the |
|
825 coordinates relative to the scene. |
|
826 |
|
827 \snippet examples/graphicsview/diagramscene/arrow.cpp 6 |
|
828 |
|
829 We calculate the angle between the x-axis and the line of the |
|
830 arrow. We need to turn the arrow head to this angle so that it |
|
831 follows the direction of the arrow. If the angle is negative we |
|
832 must turn the direction of the arrow. |
|
833 |
|
834 We can then calculate the three points of the arrow head polygon. |
|
835 One of the points is the end of the line, which now is the |
|
836 intersection between the arrow line and the end polygon. Then we |
|
837 clear the \c arrowHead polygon from the previous calculated arrow |
|
838 head and set these new points. |
|
839 |
|
840 \snippet examples/graphicsview/diagramscene/arrow.cpp 7 |
|
841 |
|
842 If the line is selected, we draw two dotted lines that are |
|
843 parallel with the line of the arrow. We do not use the default |
|
844 implementation, which uses \l{QGraphicsItem::}{boundingRect()} |
|
845 because the QRect bounding rectangle is considerably larger than |
|
846 the line. |
|
847 */ |