Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
graphicsview.qdoc
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
3
4/*!
5 \page graphicsview.html
6 \title Graphics View Framework
7 \ingroup qt-graphics
8 \ingroup qt-basic-concepts
9
10 \brief An overview of the Graphics View framework for interactive 2D
11 graphics.
12
13 \keyword Graphics View
14 \keyword GraphicsView
15 \keyword Graphics
16 \keyword Canvas
17 \since 4.2
18
19 Graphics View provides a surface for managing and interacting with a large
20 number of custom-made 2D graphical items, and a view widget for
21 visualizing the items, with support for zooming and rotation.
22
23 The framework includes an event propagation architecture that allows
24 precise double-precision interaction capabilities for the items on the
25 scene. Items can handle key events, mouse press, move, release and
26 double click events, and they can also track mouse movement.
27
28 Graphics View uses a BSP (Binary Space Partitioning) tree to provide very
29 fast item discovery, and as a result of this, it can visualize large
30 scenes in real-time, even with millions of items.
31
32 Graphics View was introduced in Qt 4.2, replacing its predecessor,
33 QCanvas.
34
35 \section1 The Graphics View Architecture
36
37 Graphics View provides an item-based approach to model-view programming,
38 much like InterView's convenience classes QTableView, QTreeView and
39 QListView. Several views can observe a single scene, and the scene
40 contains items of varying geometric shapes.
41
42 \section2 The Scene
43
44 QGraphicsScene provides the Graphics View scene. The scene has the
45 following responsibilities:
46
47 \list
48 \li Providing a fast interface for managing a large number of items
49 \li Propagating events to each item
50 \li Managing item state, such as selection and focus handling
51 \li Providing untransformed rendering functionality; mainly for printing
52 \endlist
53
54 The scene serves as a container for QGraphicsItem objects. Items are
55 added to the scene by calling QGraphicsScene::addItem(), and then
56 retrieved by calling one of the many item discovery functions.
57 QGraphicsScene::items() and its overloads return all items contained
58 by or intersecting with a point, a rectangle, a polygon or a general
59 vector path. QGraphicsScene::itemAt() returns the topmost item at a
60 particular point. All item discovery functions return the items in
61 descending stacking order (i.e., the first returned item is topmost,
62 and the last item is bottom-most).
63
64 \snippet graphicsview/graphicsview.cpp 0
65
66 QGraphicsScene's event propagation architecture schedules scene events
67 for delivery to items, and also manages propagation between items. If
68 the scene receives a mouse press event at a certain position, the
69 scene passes the event on to whichever item is at that position.
70
71 QGraphicsScene also manages certain item states, such as item
72 selection and focus. You can select items on the scene by calling
73 QGraphicsScene::setSelectionArea(), passing an arbitrary shape. This
74 functionality is also used as a basis for rubberband selection in
75 QGraphicsView. To get the list of all currently selected items, call
76 QGraphicsScene::selectedItems(). Another state handled by
77 QGraphicsScene is whether or not an item has keyboard input focus. You
78 can set focus on an item by calling QGraphicsScene::setFocusItem() or
79 QGraphicsItem::setFocus(), or get the current focus item by calling
80 QGraphicsScene::focusItem().
81
82 Finally, QGraphicsScene allows you to render parts of the scene into a
83 paint device through the QGraphicsScene::render() function. You can
84 read more about this in the Printing section later in this document.
85
86 \section2 The View
87
88 QGraphicsView provides the view widget, which visualizes the contents
89 of a scene. You can attach several views to the same scene, to provide
90 several viewports into the same data set. The view widget is a scroll
91 area, and provides scroll bars for navigating through large scenes. To
92 enable OpenGL support, you can set a QOpenGLWidget as the viewport by
93 calling QGraphicsView::setViewport().
94
95 \snippet graphicsview/graphicsview.cpp 1
96
97 The view receives input events from the keyboard and mouse, and
98 translates these to scene events (converting the coordinates used
99 to scene coordinates where appropriate), before sending the events
100 to the visualized scene.
101
102 Using its transformation matrix, QGraphicsView::transform(), the view can
103 \e transform the scene's coordinate system. This allows advanced
104 navigation features such as zooming and rotation. For convenience,
105 QGraphicsView also provides functions for translating between view and
106 scene coordinates: QGraphicsView::mapToScene() and
107 QGraphicsView::mapFromScene().
108
109 \image graphicsview-view.png {Grid of computer chips}
110
111 \section2 The Item
112
113 QGraphicsItem is the base class for graphical items in a
114 scene. Graphics View provides several standard items for typical
115 shapes, such as rectangles (QGraphicsRectItem), ellipses
116 (QGraphicsEllipseItem) and text items (QGraphicsTextItem), but the
117 most powerful QGraphicsItem features are available when you write a
118 custom item. Among other things, QGraphicsItem supports the following
119 features:
120
121 \list
122 \li Mouse press, move, release and double click events, as well as mouse
123 hover events, wheel events, and context menu events.
124 \li Keyboard input focus, and key events
125 \li Drag and drop
126 \li Grouping, both through parent-child relationships, and with
127 QGraphicsItemGroup
128 \li Collision detection
129 \endlist
130
131 Items live in a local coordinate system, and like QGraphicsView, it
132 also provides many functions for mapping coordinates between the item
133 and the scene, and from item to item. Also, like QGraphicsView, it can
134 transform its coordinate system using a matrix:
135 QGraphicsItem::transform(). This is useful for rotating and scaling
136 individual items.
137
138 Items can contain other items (children). Parent items'
139 transformations are inherited by all its children. Regardless of an
140 item's accumulated transformation, though, all its functions (e.g.,
141 QGraphicsItem::contains(), QGraphicsItem::boundingRect(),
142 QGraphicsItem::collidesWith()) still operate in local coordinates.
143
144 QGraphicsItem supports collision detection through the
145 QGraphicsItem::shape() function, and QGraphicsItem::collidesWith(),
146 which are both virtual functions. By returning your item's shape as a
147 local coordinate QPainterPath from QGraphicsItem::shape(),
148 QGraphicsItem will handle all collision detection for you. If you want
149 to provide your own collision detection, however, you can reimplement
150 QGraphicsItem::collidesWith().
151
152 \image graphicsview-items.png {Various shapes and graphics on a grid}
153
154 \section1 Classes in the Graphics View Framework
155
156 These classes provide a framework for creating interactive applications.
157
158 \annotatedlist graphicsview-api
159
160 \section1 The Graphics View Coordinate System
161
162 Graphics View is based on the Cartesian coordinate system; items'
163 position and geometry on the scene are represented by sets of two
164 numbers: the x-coordinate, and the y-coordinate. When observing a scene
165 using an untransformed view, one unit on the scene is represented by
166 one pixel on the screen.
167
168 \note The inverted Y-axis coordinate system (where \c y grows upwards)
169 is unsupported as Graphics Views uses Qt's coordinate system.
170
171 There are three effective coordinate systems in play in Graphics View:
172 Item coordinates, scene coordinates, and view coordinates. To simplify
173 your implementation, Graphics View provides convenience functions that
174 allow you to map between the three coordinate systems.
175
176 When rendering, Graphics View's scene coordinates correspond to
177 QPainter's \e logical coordinates, and view coordinates are the
178 same as \e device coordinates. In the \l{Coordinate System}
179 documentation, you can read about the relationship between
180 logical coordinates and device coordinates.
181
182 \image graphicsview-parentchild.png
183 {Several coordinate system transformation}
184
185 \section2 Item Coordinates
186
187 Items live in their own local coordinate system. Their coordinates
188 are usually centered around its center point (0, 0), and this is
189 also the center for all transformations. Geometric primitives in the
190 item coordinate system are often referred to as item points, item
191 lines, or item rectangles.
192
193 When creating a custom item, item coordinates are all you need to
194 worry about; QGraphicsScene and QGraphicsView will perform all
195 transformations for you. This makes it very easy to implement custom
196 items. For example, if you receive a mouse press or a drag enter
197 event, the event position is given in item coordinates. The
198 QGraphicsItem::contains() virtual function, which returns \c true if a
199 certain point is inside your item, and false otherwise, takes a
200 point argument in item coordinates. Similarly, an item's bounding
201 rect and shape are in item coordinates.
202
203 At item's \e position is the coordinate of the item's center point
204 in its parent's coordinate system; sometimes referred to as \e
205 parent coordinates. The scene is in this sense regarded as all
206 parent-less items' "parent". Top level items' position are in scene
207 coordinates.
208
209 Child coordinates are relative to the parent's coordinates. If the
210 child is untransformed, the difference between a child coordinate
211 and a parent coordinate is the same as the distance between the
212 items in parent coordinates. For example: If an untransformed child
213 item is positioned precisely in its parent's center point, then the
214 two items' coordinate systems will be identical. If the child's
215 position is (10, 0), however, the child's (0, 10) point will
216 correspond to its parent's (10, 10) point.
217
218 Because items' position and transformation are relative to the
219 parent, child items' coordinates are unaffected by the parent's
220 transformation, although the parent's transformation implicitly
221 transforms the child. In the above example, even if the parent is
222 rotated and scaled, the child's (0, 10) point will still correspond
223 to the parent's (10, 10) point. Relative to the scene, however, the
224 child will follow the parent's transformation and position. If the
225 parent is scaled (2x, 2x), the child's position will be at scene
226 coordinate (20, 0), and its (10, 0) point will correspond to the
227 point (40, 0) on the scene.
228
229 With QGraphicsItem::pos() being one of the few exceptions,
230 QGraphicsItem's functions operate in item coordinates, regardless of
231 the item, or any of its parents' transformation. For example, an
232 item's bounding rect (i.e. QGraphicsItem::boundingRect()) is always
233 given in item coordinates.
234
235 \section2 Scene Coordinates
236
237 The scene represents the base coordinate system for all its items.
238 The scene coordinate system describes the position of each top-level
239 item, and also forms the basis for all scene events delivered to the
240 scene from the view. Each item on the scene has a scene position
241 and bounding rectangle (QGraphicsItem::scenePos(),
242 QGraphicsItem::sceneBoundingRect()), in addition to its local item
243 pos and bounding rectangle. The scene position describes the item's
244 position in scene coordinates, and its scene bounding rect forms the
245 basis for how QGraphicsScene determines what areas of the scene have
246 changed. Changes in the scene are communicated through the
247 QGraphicsScene::changed() signal, and the argument is a list of
248 scene rectangles.
249
250 \section2 View Coordinates
251
252 View coordinates are the coordinates of the widget. Each unit in
253 view coordinates corresponds to one pixel. What's special about this
254 coordinate system is that it is relative to the widget, or viewport,
255 and unaffected by the observed scene. The top left corner of
256 QGraphicsView's viewport is always (0, 0), and the bottom right
257 corner is always (viewport width, viewport height). All mouse events
258 and drag and drop events are originally received as view
259 coordinates, and you need to map these coordinates to the scene in
260 order to interact with items.
261
262 \section2 Coordinate Mapping
263
264 Often when dealing with items in a scene, it can be useful to map
265 coordinates and arbitrary shapes from the scene to an item, from
266 item to item, or from the view to the scene. For example, when you
267 click your mouse in QGraphicsView's viewport, you can ask the scene
268 what item is under the cursor by calling
269 QGraphicsView::mapToScene(), followed by
270 QGraphicsScene::itemAt(). If you want to know where in the viewport
271 an item is located, you can call QGraphicsItem::mapToScene() on the
272 item, then QGraphicsView::mapFromScene() on the view. Finally, if
273 you use want to find what items are inside a view ellipse, you can
274 pass a QPainterPath to mapToScene(), and then pass the mapped path
275 to QGraphicsScene::items().
276
277 You can map coordinates and shapes to and from an item's scene by
278 calling QGraphicsItem::mapToScene() and
279 QGraphicsItem::mapFromScene(). You can also map to an item's parent
280 item by calling QGraphicsItem::mapToParent() and
281 QGraphicsItem::mapFromParent(), or between items by calling
282 QGraphicsItem::mapToItem() and QGraphicsItem::mapFromItem(). All
283 mapping functions can map both points, rectangles, polygons and
284 paths.
285
286 The same mapping functions are available in the view, for mapping to
287 and from the scene. QGraphicsView::mapFromScene() and
288 QGraphicsView::mapToScene(). To map from a view to an item, you
289 first map to the scene, and then map from the scene to the item.
290
291 \section1 Key Features
292
293 \section2 Zooming and rotating
294
295 QGraphicsView supports the same affine transformations as QPainter
296 does through QGraphicsView::setMatrix(). By applying a transformation
297 to the view, you can easily add support for common navigation features
298 such as zooming and rotating.
299
300 Here is an example of how to implement zoom and rotate slots in a
301 subclass of QGraphicsView:
302
303 \snippet graphicsview/graphicsview_snippet.cpp 2
304
305 The slots could be connected to \l{QToolButton}{QToolButtons} with
306 \l{QAbstractButton::autoRepeat}{autoRepeat} enabled.
307
308 QGraphicsView keeps the center of the view aligned when you transform
309 the view.
310
311 See also the \l{Elastic Nodes Example}{Elastic Nodes} example for
312 code that shows how to implement basic zooming features.
313
314 \section2 Printing
315
316 Graphics View provides single-line printing through its rendering
317 functions, QGraphicsScene::render() and QGraphicsView::render(). The
318 functions provide the same API: You can have the scene or the view
319 render all or parts of their contents into any paint device by passing
320 a QPainter to either of the rendering functions. This example shows
321 how to print the whole scene into a full page, using QPrinter.
322
323 \snippet graphicsview/graphicsview.cpp 3
324
325 The difference between the scene and view rendering functions is that
326 one operates in scene coordinates, and the other in view coordinates.
327 QGraphicsScene::render() is often preferred for printing whole
328 segments of a scene untransformed, such as for plotting geometrical
329 data, or for printing a text document. QGraphicsView::render(), on the
330 other hand, is suitable for taking screenshots; its default behavior
331 is to render the exact contents of the viewport using the provided
332 painter.
333
334 \snippet graphicsview/graphicsview.cpp 4
335
336 When the source and target areas' sizes do not match, the source
337 contents are stretched to fit into the target area. By passing a
338 Qt::AspectRatioMode to the rendering function you are using, you can
339 choose to maintain or ignore the aspect ratio of the scene when the
340 contents are stretched.
341
342 \section2 Drag and Drop
343
344 Because QGraphicsView inherits QWidget indirectly, it already provides
345 the same drag and drop functionality that QWidget provides. In
346 addition, as a convenience, the Graphics View framework provides drag
347 and drop support for the scene, and for each and every item. As the
348 view receives a drag, it translates the drag and drop events into a
349 QGraphicsSceneDragDropEvent, which is then forwarded to the scene. The
350 scene takes over scheduling of this event, and sends it to the first
351 item under the mouse cursor that accepts drops.
352
353 To start a drag from an item, create a QDrag object, passing a pointer
354 to the widget that starts the drag. Items can be observed by many
355 views at the same time, but only one view can start the drag. Drags
356 are in most cases started as a result of pressing or moving the mouse,
357 so in mousePressEvent() or mouseMoveEvent(), you can get the
358 originating widget pointer from the event. For example:
359
360 \snippet graphicsview/graphicsview.cpp 5
361
362 To intercept drag and drop events for the scene, you reimplement
363 QGraphicsScene::dragEnterEvent() and whichever event handlers your
364 particular scene needs, in a QGraphicsItem subclass. You can read more
365 about drag and drop in Graphics View in the documentation for each of
366 QGraphicsScene's event handlers.
367
368 Items can enable drag and drop support by calling
369 QGraphicsItem::setAcceptDrops(). To handle the incoming drag,
370 reimplement QGraphicsItem::dragEnterEvent(),
371 QGraphicsItem::dragMoveEvent(), QGraphicsItem::dragLeaveEvent(), and
372 QGraphicsItem::dropEvent().
373
374 See also the \l{Drag and Drop Robot Example}{Drag and Drop Robot} example
375 for a demonstration of Graphics View's support for drag and drop
376 operations.
377
378 \section2 Cursors and Tooltips
379
380 Like QWidget, QGraphicsItem also supports cursors
381 (QGraphicsItem::setCursor()), and tooltips
382 (QGraphicsItem::setToolTip()). The cursors and tooltips are activated
383 by QGraphicsView as the mouse cursor enters the item's area (detected
384 by calling QGraphicsItem::contains()).
385
386 You can also set a default cursor directly on the view by calling
387 QGraphicsView::setCursor().
388
389 See also the \l{Drag and Drop Robot Example}{Drag and Drop Robot}
390 example for code that implements tooltips and cursor shape handling.
391
392 \section2 Animation
393
394 Graphics View supports animation at several levels. You can
395 easily assemble animation by using the Animation Framework.
396 For that you'll need your items to inherit from
397 QGraphicsObject and associate QPropertyAnimation with
398 them. QPropertyAnimation allows to animate any QObject
399 property.
400
401 Another option is to create a custom item that inherits from QObject
402 and QGraphicsItem. The item can the set up its own timers, and control
403 animations with incremental steps in QObject::timerEvent().
404
405 A third option, which is mostly available for compatibility with
406 QCanvas in Qt 3, is to \e advance the scene by calling
407 QGraphicsScene::advance(), which in turn calls
408 QGraphicsItem::advance().
409
410 \section2 OpenGL Rendering
411
412 To enable OpenGL rendering, you simply set a new QOpenGLWidget as the
413 viewport of QGraphicsView by calling QGraphicsView::setViewport(). If
414 you want OpenGL with antialiasing, you need to set a QSurfaceFormat
415 with the needed sample count (see QSurfaceFormat::setSamples()).
416
417 Example:
418
419 \snippet graphicsview/graphicsview.cpp 6
420
421 \section2 Item Groups
422
423 By making an item a child of another, you can achieve the most
424 essential feature of item grouping: the items will move together, and
425 all transformations are propagated from parent to child.
426
427 In addition, QGraphicsItemGroup is a special item that combines child
428 event handling with a useful interface for adding and removing items
429 to and from a group. Adding an item to a QGraphicsItemGroup will keep
430 the item's original position and transformation, whereas reparenting
431 items in general will cause the child to reposition itself relative to
432 its new parent. For convenience, you can create
433 \l{QGraphicsItemGroup}s through the scene by calling
434 QGraphicsScene::createItemGroup().
435
436 \section2 Widgets and Layouts
437
438 Qt 4.4 introduced support for geometry and layout-aware items through
439 QGraphicsWidget. This special base item is similar to QWidget, but
440 unlike QWidget, it doesn't inherit from QPaintDevice; rather from
441 QGraphicsItem instead. This allows you to write complete widgets with
442 events, signals & slots, size hints and policies, and you can also
443 manage your widgets geometries in layouts through
444 QGraphicsLinearLayout and QGraphicsGridLayout.
445
446 \section3 QGraphicsWidget
447
448 Building on top of QGraphicsItem's capabilities and lean footprint,
449 QGraphicsWidget provides the best of both worlds: extra
450 functionality from QWidget, such as the style, font, palette, layout
451 direction, and its geometry, and resolution independence and
452 transformation support from QGraphicsItem. Because Graphics View
453 uses real coordinates instead of integers, QGraphicsWidget's
454 geometry functions also operate on QRectF and QPointF. This also
455 applies to frame rects, margins and spacing. With QGraphicsWidget
456 it's not uncommon to specify contents margins of (0.5, 0.5, 0.5,
457 0.5), for example. You can create both subwidgets and "top-level"
458 windows; in some cases you can now use Graphics View for advanced
459 MDI applications.
460
461 Some of QWidget's properties are supported, including window flags
462 and attributes, but not all. You should refer to QGraphicsWidget's
463 class documentation for a complete overview of what is and what is
464 not supported. For example, you can create decorated windows by
465 passing the Qt::Window window flag to QGraphicsWidget's constructor,
466 but Graphics View currently doesn't support the Qt::Sheet and
467 Qt::Drawer flags that are common on \macos.
468
469 \section3 QGraphicsLayout
470
471 QGraphicsLayout is part of a second-generation layout framework
472 designed specifically for QGraphicsWidget. Its API is very similar
473 to that of QLayout. You can manage widgets and sublayouts inside
474 either QGraphicsLinearLayout and QGraphicsGridLayout. You can also
475 easily write your own layout by subclassing QGraphicsLayout
476 yourself, or add your own QGraphicsItem items to the layout by
477 writing an adaptor subclass of QGraphicsLayoutItem.
478
479 \section2 Embedded Widget Support
480
481 Graphics View provides seamless support for embedding any widget
482 into the scene. You can embed simple widgets, such as QLineEdit or
483 QPushButton, complex widgets such as QTabWidget, and even complete
484 main windows. To embed your widget to the scene, simply call
485 QGraphicsScene::addWidget(), or create an instance of
486 QGraphicsProxyWidget to embed your widget manually.
487
488 Through QGraphicsProxyWidget, Graphics View is able to deeply
489 integrate the client widget features including its cursors,
490 tooltips, mouse, tablet and keyboard events, child widgets,
491 animations, pop-ups (e.g., QComboBox or QCompleter), and the widget's
492 input focus and activation. QGraphicsProxyWidget even integrates the
493 embedded widget's tab order so that you can tab in and out of
494 embedded widgets. You can even embed a new QGraphicsView into your
495 scene to provide complex nested scenes.
496
497 When transforming an embedded widget, Graphics View makes sure that
498 the widget is transformed resolution independently, allowing the
499 fonts and style to stay crisp when zoomed in. (Note that the effect
500 of resolution independence depends on the style.)
501
502 \section1 Performance
503
504 \section2 Floating Point Instructions
505
506 In order to accurately and quickly apply transformations and effects to
507 items, Graphics View is built with the assumption that the user's hardware
508 is able to provide reasonable performance for floating point instructions.
509
510 Many workstations and desktop computers are equipped with suitable hardware
511 to accelerate this kind of computation, but some embedded devices may only
512 provide libraries to handle mathematical operations or emulate floating
513 point instructions in software.
514
515 As a result, certain kinds of effects may be slower than expected on certain
516 devices. It may be possible to compensate for this performance hit by making
517 optimizations in other areas; for example, by using \l{#OpenGL Rendering}{OpenGL}
518 to render a scene. However, any such optimizations may themselves cause a
519 reduction in performance if they also rely on the presence of floating point
520 hardware.
521*/