圖形視圖提供用於管理大量定製 2D 圖形項並與之交互的錶麵,和用於可視化這些項的視圖 Widget (支持縮放和鏇轉)。
框架包括事件傳播體係結構,允許將精確雙精度交互能力用於場景項。項可以處理按鍵事件,鼠標按下、移動、釋放及雙擊事件,且它們還可以跟蹤鼠標移動。
圖形視圖使用 BSP (二進製空間分區) 樹以提供非常快速的項探索,因此,它可以實時可視化大型場景,甚至具有數百萬的項。
圖形視圖在 Qt 4.2 引入,替換其前身 QCanvas。
話題:
圖形視圖提供基於項的模型/視圖編程途徑,非常像 InterView 方便類 QTableView , QTreeView and QListView 。多個視圖可以觀測一個場景,且場景包含各種幾何形狀的項。
QGraphicsScene 提供圖形視圖場景。場景有以下職責:
場景充當容器為 QGraphicsItem 對象。將項添加到場景通過調用 QGraphicsScene::addItem (),然後通過調用許多項探索函數之一檢索。 QGraphicsScene::items () 及其重載返迴點、矩形、多邊形或一般嚮量路徑所包含或與之相交的所有項。 QGraphicsScene::itemAt () 返迴特定點的最頂項。所有項探索函數按降序堆疊次序返迴項 (即:第一返迴項最頂,最後項最底)。
QGraphicsScene scene; QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100)); QGraphicsItem *item = scene.itemAt(50, 50); // item == rect
QGraphicsScene 的事件傳播體係結構調度要交付給項的場景事件,並管理項之間的傳播。若場景在某個位置收到鼠標按下事件,場景將事件傳遞給該位置的任何項。
QGraphicsScene 還管理某些項狀態 (譬如:項選定和聚焦)。可以選擇場景中的項通過調用 QGraphicsScene::setSelectionArea (),傳遞任意形狀。此功能還用作選擇橡皮筋的基礎在 QGraphicsView 。要獲取所有目前選中項的列錶,調用 QGraphicsScene::selectedItems ()。另一狀態的處理通過 QGraphicsScene 為項是否擁有鍵盤輸入聚焦。可以設置項聚焦通過調用 QGraphicsScene::setFocusItem () 或 QGraphicsItem::setFocus (),或獲取當前聚焦項通過調用 QGraphicsScene::focusItem ().
最後, QGraphicsScene 允許將場景部分渲染進繪圖設備透過 QGraphicsScene::render () 函數。可以在此文檔稍後的打印章節閱讀更多有關這。
QGraphicsView provides the view widget, which visualizes the contents of a scene. You can attach several views to the same scene, to provide several viewports into the same data set. The view widget is a scroll area, and provides scroll bars for navigating through large scenes. To enable OpenGL support, you can set a QGLWidget as the viewport by calling QGraphicsView::setViewport ().
QGraphicsScene scene; myPopulateScene(&scene); QGraphicsView view(&scene); view.show();
視圖從鍵盤和鼠標接收輸入事件,並將這些事件轉換為場景事件 (將所用坐標轉換為閤適場景坐標),在將事件發送給可視化場景之前。
使用其變換矩陣, QGraphicsView::transform (),視圖可以 transform 場景的坐標係。這允許高級導航特徵 (譬如:縮放和鏇轉)。為方便起見, QGraphicsView 還提供視圖和場景坐標之間的翻譯函數: QGraphicsView::mapToScene () 和 QGraphicsView::mapFromScene ().
QGraphicsItem 是場景圖形項的基類。Graphics View 為典型形狀提供瞭幾種標準項,譬如矩形 ( QGraphicsRectItem ),橢圓 ( QGraphicsEllipseItem ) 和文本項 ( QGraphicsTextItem ),但最強大的 QGraphicsItem 特徵是可用的,當編寫自定義項時。除其它事情外, QGraphicsItem 支持下列特徵:
項活在本地坐標係中,且像 QGraphicsView ,它還提供瞭用於在項和場景之間,從項到項映射坐標的許多函數。另外,像 QGraphicsView ,它可以使用矩陣變換其坐標係: QGraphicsItem::transform ()。這對鏇轉和比例縮放單個項很有用。
項可以包含其它項 (子級)。父級項的變換由其所有子級繼承。雖然可以不管項的纍計變換,它的所有函數 (如 QGraphicsItem::contains (), QGraphicsItem::boundingRect (),QGraphicsItem::collidesWith()) 仍運轉在本地坐標。
QGraphicsItem 支持碰撞檢測透過 QGraphicsItem::shape () 函數,和 QGraphicsItem::collidesWith(),兩者都是虛函數。通過將項的形狀返迴作為本地坐標 QPainterPath from QGraphicsItem::shape (), QGraphicsItem 將為您處理所有碰撞檢測。不管怎樣,若想要提供自己的碰撞檢測,可以重實現 QGraphicsItem::collidesWith()。
這些類提供用於創建交互應用程序的框架。
| QGraphicsEffect | 用於所有圖形效果的基類 |
| QGraphicsAnchor | 錶示 QGraphicsAnchorLayout 中 2 項之間的錨點 |
| QGraphicsAnchorLayout | 可以在圖形視圖中將 Widget 錨定在一起的布局 |
| QGraphicsGridLayout | 用於在圖形視圖中管理 Widget 的柵格布局 |
| QAbstractGraphicsShapeItem | 用於所有路徑項的公共基 |
| QGraphicsEllipseItem | 可以添加到 QGraphicsScene 的橢圓項 |
| QGraphicsItem | QGraphicsScene 中所有圖形項的基類 |
| QGraphicsItemGroup | 將一組項視為單項的容器 |
| QGraphicsLineItem | 可以添加到 QGraphicsScene 的綫項 |
| QGraphicsObject | 基類用於所有要求信號、槽及特性的圖形項 |
| QGraphicsPathItem | 可添加到 QGraphicsScene 的路徑項 |
| QGraphicsPixmapItem | 可以添加到 QGraphicsScene 的像素圖項 |
| QGraphicsPolygonItem | 可以添加到 QGraphicsScene 的多邊形項 |
| QGraphicsRectItem | 可以添加到 QGraphicsScene 的矩形項 |
| QGraphicsSimpleTextItem | 可添加到 QGraphicsScene 的簡單文本路徑項 |
| QGraphicsTextItem | 可添加到 QGraphicsScene,以顯示格式化文本的文本項 |
| QGraphicsLayout | 基類為圖形視圖中的所有布局 |
| QGraphicsLayoutItem | 可以被繼承以允許自定義項由布局進行管理 |
| QGraphicsLinearLayout | 用於在圖形視圖中管理 Widget 的水平或垂直布局 |
| QGraphicsProxyWidget | 用於將 QWidget 嵌入 QGraphicsScene 的代理層 |
| QGraphicsScene | 用於管理大量 2D 圖形項的錶麵 |
| QGraphicsSceneContextMenuEvent | 在圖形視圖框架中的上下文菜單事件 |
| QGraphicsSceneDragDropEvent | 用於圖形視圖框架的拖放事件 |
| QGraphicsSceneEvent | 基類為所有圖形視圖相關事件 |
| QGraphicsSceneHelpEvent | 當請求工具提示時的事件 |
| QGraphicsSceneHoverEvent | 在圖形視圖框架中的懸停事件 |
| QGraphicsSceneMouseEvent | 在圖形視圖框架中的鼠標事件 |
| QGraphicsSceneMoveEvent | 用於在圖形視圖框架中移動 Widget 的事件 |
| QGraphicsSceneResizeEvent | 用於在圖形視圖框架中重置 Widget 大小的事件 |
| QGraphicsSceneWheelEvent | 在圖形視圖框架中的滾輪事件 |
| QGraphicsTransform | 抽象基類用於在 QGraphicsItems 構建高級變換 |
| QGraphicsView | 用於顯示 QGraphicsScene 內容的 Widget |
| QGraphicsWidget | 基類用於 QGraphicsScene 中的所有 Widget 項 |
| QStyleOptionGraphicsItem | 用於繪製 QGraphicsItem 的所需描述參數 |
| QGraphicsSvgItem | 用於渲染 SVG 文件內容的 QGraphicsItem |
圖形視圖是基於笛卡爾坐標係;項位置和場景幾何圖形的錶示均是按 2 數字的集:X 坐標和 Y 坐標。當觀測使用未轉換視圖的場景時,1 屏幕像素錶示 1 場景單位。
注意:
反轉 Y 軸的坐標係 (其
y
嚮上增長) 不支持,因為圖形視圖使用 Qt 的坐標係。
圖形視圖有 3 種有效坐標係:項坐標、場景坐標及視圖坐標。為簡化實現,圖形視圖提供瞭允許在 3 種坐標係之間映射的方便函數。
當渲染時,圖形視圖的場景坐標對應 QPainter 's logical 坐標,和視圖坐標如同 device 坐標。在 坐標係 文檔編製,可以瞭解有關邏輯坐標和設備坐標之間的關係。
Items live in their own local coordinate system. Their coordinates are usually centered around its center point (0, 0), and this is also the center for all transformations. Geometric primitives in the item coordinate system are often referred to as item points, item lines, or item rectangles.
當創建自定義項時,項坐標是需要擔心的全部;
QGraphicsScene
and
QGraphicsView
will perform all transformations for you. This makes it very easy to implement custom items. For example, if you receive a mouse press or a drag enter event, the event position is given in item coordinates. The
QGraphicsItem::contains
() virtual function, which returns
true
if a certain point is inside your item, and false otherwise, takes a point argument in item coordinates. Similarly, an item's bounding rect and shape are in item coordinates.
At item's position is the coordinate of the item's center point in its parent's coordinate system; sometimes referred to as parent coordinates. The scene is in this sense regarded as all parent-less items' "parent". Top level items' position are in scene coordinates.
Child coordinates are relative to the parent's coordinates. If the child is untransformed, the difference between a child coordinate and a parent coordinate is the same as the distance between the items in parent coordinates. For example: If an untransformed child item is positioned precisely in its parent's center point, then the two items' coordinate systems will be identical. If the child's position is (10, 0), however, the child's (0, 10) point will correspond to its parent's (10, 10) point.
Because items' position and transformation are relative to the parent, child items' coordinates are unaffected by the parent's transformation, although the parent's transformation implicitly transforms the child. In the above example, even if the parent is rotated and scaled, the child's (0, 10) point will still correspond to the parent's (10, 10) point. Relative to the scene, however, the child will follow the parent's transformation and position. If the parent is scaled (2x, 2x), the child's position will be at scene coordinate (20, 0), and its (10, 0) point will correspond to the point (40, 0) on the scene.
采用 QGraphicsItem::pos () being one of the few exceptions, QGraphicsItem 's functions operate in item coordinates, regardless of the item, or any of its parents' transformation. For example, an item's bounding rect (i.e. QGraphicsItem::boundingRect ()) is always given in item coordinates.
The scene represents the base coordinate system for all its items. The scene coordinate system describes the position of each top-level item, and also forms the basis for all scene events delivered to the scene from the view. Each item on the scene has a scene position and bounding rectangle ( QGraphicsItem::scenePos (), QGraphicsItem::sceneBoundingRect ()), in addition to its local item pos and bounding rectangle. The scene position describes the item's position in scene coordinates, and its scene bounding rect forms the basis for how QGraphicsScene determines what areas of the scene have changed. Changes in the scene are communicated through the QGraphicsScene::changed () signal, and the argument is a list of scene rectangles.
View coordinates are the coordinates of the widget. Each unit in view coordinates corresponds to one pixel. What's special about this coordinate system is that it is relative to the widget, or viewport, and unaffected by the observed scene. The top left corner of QGraphicsView 's viewport is always (0, 0), and the bottom right corner is always (viewport width, viewport height). All mouse events and drag and drop events are originally received as view coordinates, and you need to map these coordinates to the scene in order to interact with items.
Often when dealing with items in a scene, it can be useful to map coordinates and arbitrary shapes from the scene to an item, from item to item, or from the view to the scene. For example, when you click your mouse in QGraphicsView 's viewport, you can ask the scene what item is under the cursor by calling QGraphicsView::mapToScene (), followed by QGraphicsScene::itemAt (). If you want to know where in the viewport an item is located, you can call QGraphicsItem::mapToScene () on the item, then QGraphicsView::mapFromScene () on the view. Finally, if you use want to find what items are inside a view ellipse, you can pass a QPainterPath to mapToScene(), and then pass the mapped path to QGraphicsScene::items ().
可以將坐標和形狀映射到/從項場景通過調用 QGraphicsItem::mapToScene () 和 QGraphicsItem::mapFromScene (). You can also map to an item's parent item by calling QGraphicsItem::mapToParent () 和 QGraphicsItem::mapFromParent (), or between items by calling QGraphicsItem::mapToItem () 和 QGraphicsItem::mapFromItem (). All mapping functions can map both points, rectangles, polygons and paths.
The same mapping functions are available in the view, for mapping to and from the scene. QGraphicsView::mapFromScene () 和 QGraphicsView::mapToScene (). To map from a view to an item, you first map to the scene, and then map from the scene to the item.
QGraphicsView 支持相同仿射變換如 QPainter does through QGraphicsView::setMatrix (). By applying a transformation to the view, you can easily add support for common navigation features such as zooming and rotating.
Here is an example of how to implement zoom and rotate slots in a subclass of QGraphicsView :
class View : public QGraphicsView { Q_OBJECT ... public slots: void zoomIn() { scale(1.2, 1.2); } void zoomOut() { scale(1 / 1.2, 1 / 1.2); } void rotateLeft() { rotate(-10); } void rotateRight() { rotate(10); } ... };
可以將槽連接到 QToolButtons with autoRepeat 被啓用。
QGraphicsView keeps the center of the view aligned when you transform the view.
另請參閱 彈性節點 example for code that shows how to implement basic zooming features.
圖形視圖提供瞭單行打印,透過其渲染函數 QGraphicsScene::render () 和 QGraphicsView::render (). The functions provide the same API: You can have the scene or the view render all or parts of their contents into any paint device by passing a QPainter to either of the rendering functions. This example shows how to print the whole scene into a full page, using QPrinter .
QGraphicsScene scene; scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green)); QPrinter printer; if (QPrintDialog(&printer).exec() == QDialog::Accepted) { QPainter painter(&printer); painter.setRenderHint(QPainter::Antialiasing); scene.render(&painter); }
The difference between the scene and view rendering functions is that one operates in scene coordinates, and the other in view coordinates. QGraphicsScene::render () is often preferred for printing whole segments of a scene untransformed, such as for plotting geometrical data, or for printing a text document. QGraphicsView::render (), on the other hand, is suitable for taking screenshots; its default behavior is to render the exact contents of the viewport using the provided painter.
QGraphicsScene scene; scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green)); QPixmap pixmap; QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing); scene.render(&painter); painter.end(); pixmap.save("scene.png");
When the source and target areas' sizes do not match, the source contents are stretched to fit into the target area. By passing a Qt::AspectRatioMode to the rendering function you are using, you can choose to maintain or ignore the aspect ratio of the scene when the contents are stretched.
因為 QGraphicsView 繼承 QWidget indirectly, it already provides the same drag and drop functionality that QWidget provides. In addition, as a convenience, the Graphics View framework provides drag and drop support for the scene, and for each and every item. As the view receives a drag, it translates the drag and drop events into a QGraphicsSceneDragDropEvent , which is then forwarded to the scene. The scene takes over scheduling of this event, and sends it to the first item under the mouse cursor that accepts drops.
要從項開始拖拽,創建 QDrag object, passing a pointer to the widget that starts the drag. Items can be observed by many views at the same time, but only one view can start the drag. Drags are in most cases started as a result of pressing or moving the mouse, so in mousePressEvent() or mouseMoveEvent(), you can get the originating widget pointer from the event. For example:
void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QMimeData *data = new QMimeData; data->setColor(Qt::green); QDrag *drag = new QDrag(event->widget()); drag->setMimeData(data); drag->start(); }
To intercept drag and drop events for the scene, you reimplement QGraphicsScene::dragEnterEvent () and whichever event handlers your particular scene needs, in a QGraphicsItem subclass. You can read more about drag and drop in Graphics View in the documentation for each of QGraphicsScene 的事件處理程序。
項可以啓用拖放支持,通過調用 QGraphicsItem::setAcceptDrops ()。要處理傳入拖拽,重實現 QGraphicsItem::dragEnterEvent (), QGraphicsItem::dragMoveEvent (), QGraphicsItem::dragLeaveEvent (),和 QGraphicsItem::dropEvent ().
另請參閱 拖放 Robot 範例,瞭解圖形視圖對拖放操作支持的演示。
像 QWidget , QGraphicsItem 還支持光標 ( QGraphicsItem::setCursor ()),和工具提示 ( QGraphicsItem::setToolTip ())。光標和工具提示的激活是通過 QGraphicsView 當鼠標光標進入項區域時 (檢測通過調用 QGraphicsItem::contains ()).
還可以直接為視圖設置默認光標通過調用 QGraphicsView::setCursor ().
另請參閱 拖放 Robot 範例,對於實現工具提示和光標形狀處理的代碼。
Graphics View supports animation at several levels. You can easily assemble animation by using the Animation Framework. For that you'll need your items to inherit from QGraphicsObject and associate QPropertyAnimation with them. QPropertyAnimation allows to animate any QObject 特性。
Another option is to create a custom item that inherits from QObject and QGraphicsItem . The item can the set up its own timers, and control animations with incremental steps in QObject::timerEvent ().
A third option, which is mostly available for compatibility with QCanvas in Qt 3, is to advance the scene by calling QGraphicsScene::advance (), which in turn calls QGraphicsItem::advance ().
To enable OpenGL rendering, you simply set a new QGLWidget as the viewport of QGraphicsView 通過調用 QGraphicsView::setViewport (). If you want OpenGL with antialiasing, you need OpenGL sample buffer support (see QGLFormat::sampleBuffers ()).
範例:
QGraphicsView view(&scene); view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
通過使項成為另一項的子級,可以達成最基本的項分組特徵:項將一起移動,且所有變換都是從父級傳播到子級。
此外, QGraphicsItemGroup is a special item that combines child event handling with a useful interface for adding and removing items to and from a group. Adding an item to a QGraphicsItemGroup will keep the item's original position and transformation, whereas reparenting items in general will cause the child to reposition itself relative to its new parent. For convenience, you can create QGraphicsItemGroup s through the scene by calling QGraphicsScene::createItemGroup ().
Qt 4.4 引入瞭對幾何和布局感知項的支持,透過 QGraphicsWidget 。 此特殊基項類似於 QWidget ,但不像 QWidget ,它未繼承自 QPaintDevice ;而是來自 QGraphicsItem 相反。這允許采用事件、信號/槽、大小提示及策略編寫完整 Widget,且還可以管理布局中的 Widget 幾何體透過 QGraphicsLinearLayout and QGraphicsGridLayout .
Building on top of QGraphicsItem 's capabilities and lean footprint, QGraphicsWidget provides the best of both worlds: extra functionality from QWidget , such as the style, font, palette, layout direction, and its geometry, and resolution independence and transformation support from QGraphicsItem . Because Graphics View uses real coordinates instead of integers, QGraphicsWidget 's geometry functions also operate on QRectF and QPointF . This also applies to frame rects, margins and spacing. With QGraphicsWidget it's not uncommon to specify contents margins of (0.5, 0.5, 0.5, 0.5), for example. You can create both subwidgets and "top-level" windows; in some cases you can now use Graphics View for advanced MDI applications.
Some of QWidget 's properties are supported, including window flags and attributes, but not all. You should refer to QGraphicsWidget 's class documentation for a complete overview of what is and what is not supported. For example, you can create decorated windows by passing the Qt::Window 窗口標誌到 QGraphicsWidget 's constructor, but Graphics View currently doesn't support the Qt::Sheet and Qt::Drawer flags that are common on macOS.
QGraphicsLayout is part of a second-generation layout framework designed specifically for QGraphicsWidget . Its API is very similar to that of QLayout . You can manage widgets and sublayouts inside either QGraphicsLinearLayout and QGraphicsGridLayout . You can also easily write your own layout by subclassing QGraphicsLayout yourself, or add your own QGraphicsItem items to the layout by writing an adaptor subclass of QGraphicsLayoutItem .
圖形視圖為將任何 Widget 嵌入場景提供無縫支持。可以嵌入簡單 Widget,譬如 QLineEdit or QPushButton , complex widgets such as QTabWidget , and even complete main windows. To embed your widget to the scene, simply call QGraphicsScene::addWidget (),或創建實例化的 QGraphicsProxyWidget to embed your widget manually.
Through QGraphicsProxyWidget , Graphics View is able to deeply integrate the client widget features including its cursors, tooltips, mouse, tablet and keyboard events, child widgets, animations, pop-ups (e.g., QComboBox or QCompleter ), and the widget's input focus and activation. QGraphicsProxyWidget even integrates the embedded widget's tab order so that you can tab in and out of embedded widgets. You can even embed a new QGraphicsView into your scene to provide complex nested scenes.
When transforming an embedded widget, Graphics View makes sure that the widget is transformed resolution independently, allowing the fonts and style to stay crisp when zoomed in. (Note that the effect of resolution independence depends on the style.)
In order to accurately and quickly apply transformations and effects to items, Graphics View is built with the assumption that the user's hardware is able to provide reasonable performance for floating point instructions.
Many workstations and desktop computers are equipped with suitable hardware to accelerate this kind of computation, but some embedded devices may only provide libraries to handle mathematical operations or emulate floating point instructions in software.
As a result, certain kinds of effects may be slower than expected on certain devices. It may be possible to compensate for this performance hit by making optimizations in other areas; for example, by using OpenGL to render a scene. However, any such optimizations may themselves cause a reduction in performance if they also rely on the presence of floating point hardware.