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