#(30):Graphics View Framework
Graphics View 提供了一種接口,用于管理大量自定義的 2D 圖形元素,并與之進行交互;還提供了用于將這些元素進行可視化顯示的觀察組件,并支持縮放和旋轉。我們通常所說的 Linux 的 KDE 桌面環境,就是建立在 Graphics View 基礎之上的(盡管新版本的 KDE 有向 QML 遷移的趨勢)。
Graphics View 框架包含了一套完整的事件體系,可以用于與場景中的元素進行雙精度的交互。這些元素同樣支持鍵盤事件、鼠標事件等。Graphics View 使用了 BSP 樹(Binary Space Partitioning tree,這是一種被廣泛應用于圖形學方面的數據結構)來提供非常快速的元素發現,也正因為如此,才能夠實現一種上百萬數量級元素的實時顯示機制。
Graphics View 最初在 Qt 4.2 引入,來取代 Qt 3 中的 QCanvas。當然,在最新的 Qt5 中,Qt3 的代碼已經不能繼續使用了(盡管在一定程度上, Qt4 還是可以使用這些遺留代碼)。
Graphics View 是一個基于元素(item)的 MV 架構的框架。它可以分成三個部分:元素 item、場景 scene 和視圖 view。
基于元素的意思是,它的每一個組件都是一個獨立的元素。這是與我們之前講到過的`QPainter`狀態機機制不同。回憶一下,使用`QPainter`繪圖,大多是采用一種面向過程的描述方式:首先使用`drawLine()`畫一條直線,然后使用`drawPolygon()`畫一個多邊形。對于 Graphics View,相同的過程可以是,首先創建一個場景(scene),然后創建一個直線對象和一個多邊形對象,再使用場景的`add()`函數,將直線和多邊形添加到場景中,最后通過視圖進行觀察,就可以看到了。乍看起來,后者似乎更加復雜,但是,如果你的圖像中包含了成千上萬的直線、多邊形之類,管理這些對象要比管理`QPainter`的繪制語句容易得多。并且,這些圖形對象也更加符合面向對象的設計要求:一個很復雜的圖形可以很方便的復用。
MV 架構的意思是,Graphics View 提供一個 model 和一個 view(正如 MVC 架構,只不過 MV 架構少了 C 這么一個組件)。所謂模型(model)就是我們添加的種種對象;所謂視圖(view)就是我們觀察這些對象的視口。同一個模型可以由很多視圖從不同的角度進行觀察,這是很常見的需求。使用 QPainter 很難實現這一點,這需要很復雜的計算,而 Graphics View 可以很容易的實現。
Graphics View 提供了`QGraphicsScene`作為場景,即是允許我們添加圖形的空間,相當于整個世界;`QGraphicsView`作為視口,也就是我們的觀察窗口,相當于照相機的取景框,這個取景框可以覆蓋整個場景,也可以是場景的一部分;`QGraphicsItem`作為圖形元件,以便添加到場景中去,Qt 內置了很多圖形,比如直線、多邊形等,它們都是繼承自`QGraphicsItem`。
下面我們通過一段代碼看看 Graphics View 的使用。
~~~
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene scene;
scene.addLine(0, 0, 150, 150);
QGraphicsView view(&scene);
view.setWindowTitle("Graphics View");
view.resize(500, 500);
view.show();
return app.exec();
}
~~~
這段代碼很簡單:首先創建一個場景,也就是`QGraphicsScene`對象。然后我們使用`addLine()`函數向場景中添加了一個直線,起始點和終點坐標分別是 (0, 0) 和 (150, 150)。可以想象,這是一個邊長 150px 的正方形的對角線。通過這兩步,我們已經有了場景和元素。之后,我們創建一個`GraphicsView`對象,綁定到一個場景上(也就是我們前面創建的 scene 對象)。注意,`QGraphicsScene`不是`QWidget`的子類,因此該構造函數并不是調用的`QGraphicsView(QWidget *parent)`。接下來,我們可以運行一下代碼:
[](http://files.devbean.net/images/2012/12/graphics-view-demo.png)
我們看到,這個直線自動在視圖居中顯示。這并不需要我們進行任何額外的代碼。如果不想這么做,我們可以給 scene 設置一下`sceneRect()`屬性:
~~~
QGraphicsScene scene;
scene.setSceneRect(0, 0, 300, 300);
scene.addLine(0, 0, 150, 150);
QGraphicsView view(&scene);
view.setWindowTitle("Graphics View");
// view.resize(500, 500);
view.show();
~~~
不僅如此,我們還去掉了`view.resize()`一行。`QGraphicsScene`的`sceneRect`屬性供`QGraphicsView`確定視圖默認的滾動條區域,并且協助`QGraphicsScene`管理元素索引。之所以去掉`view.resize()`一行,是因為我們讓系統去決定視圖的最小尺寸(否則的話,我們需要手動將窗口標題欄等的大小同時考慮設置)。
- (1)序
- (2)Qt 簡介
- (3)Hello, world!
- (4)信號槽
- (5)自定義信號槽
- (6)Qt 模塊簡介
- (7)MainWindow 簡介
- (8)添加動作
- (9)資源文件
- (10)對象模型
- (11)布局管理器
- (12)菜單欄、工具欄和狀態欄
- (13)對話框簡介
- (14)對話框數據傳遞
- (15)標準對話框 QMessageBox
- (16)深入 Qt5 信號槽新語法
- (17)文件對話框
- (18)事件
- (19)事件的接受與忽略
- (21)事件過濾器
- (22)事件總結
- (23)自定義事件
- (24)Qt 繪制系統簡介
- (25)畫刷和畫筆
- (26)反走樣
- (27)漸變
- (28)坐標系統
- (29)繪制設備
- (30)Graphics View Framework
- (31)貪吃蛇游戲(1)
- (32)貪吃蛇游戲(2)
- (33)貪吃蛇游戲(3)
- (34)貪吃蛇游戲(4)
- (35)文件
- (36)二進制文件讀寫
- (37)文本文件讀寫
- (38)存儲容器
- (39)遍歷容器
- (40)隱式數據共享
- (41)model/view 架構
- (42)QListWidget、QTreeWidget 和 QTableWidget
- (43)QStringListModel
- (44)QFileSystemModel
- (45)模型
- (46)視圖和委托
- (47)視圖選擇
- (48)QSortFilterProxyModel
- (49)自定義只讀模型
- (50)自定義可編輯模型
- (51)布爾表達式樹模型
- (52)使用拖放
- (53)自定義拖放數據
- (54)剪貼板
- (55)數據庫操作
- (56)使用模型操作數據庫
- (57)可視化顯示數據庫數據
- (58)編輯數據庫外鍵
- (59)使用流處理 XML
- (60)使用 DOM 處理 XML
- (61)使用 SAX 處理 XML
- (62)保存 XML
- (63)使用 QJson 處理 JSON
- (64)使用 QJsonDocument 處理 JSON
- (65)訪問網絡(1)
- (66)訪問網絡(2)
- (67)訪問網絡(3)
- (68)訪問網絡(4)
- (69)進程
- (70)進程間通信
- (71)線程簡介
- (72)線程和事件循環
- (73)Qt 線程相關類
- (74)線程和 QObject
- (75)線程總結
- (76)QML 和 QtQuick 2
- (77)QML 語法
- (78)QML 基本元素
- (79)QML 組件
- (80)定位器
- (81)元素布局
- (82)輸入元素
- (83)Qt Quick Controls
- (84)Repeater
- (85)動態視圖
- (86)視圖代理
- (87)模型-視圖高級技術
- (88)Canvas
- (89)Canvas(續)