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 仍是可使用這些遺留代碼)。app
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
。code
下面咱們經過一段代碼看看 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)
。接下來,咱們能夠運行一下代碼:繼承
咱們看到,這個直線自動在視圖居中顯示。這並不須要咱們進行任何額外的代碼。若是不想這麼作,咱們能夠給 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()
一行,是由於咱們讓系統去決定視圖的最小尺寸(不然的話,咱們須要手動將窗口標題欄等的大小同時考慮設置)。