Qt開發技術:圖形檢視框架(一)基本介紹

紅胖子(紅模仿)發表於2021-04-17

前話

  使用到Qt的檢視框架。

 

Qt檢視框架介紹

簡介

  圖形檢視框架(The Graphic View Framework)用於管理和與大量定製的二維圖形專案互動,以及用於視覺化專案的檢視小部件,支援縮放和旋轉。
  在這裡插入圖片描述

  該框架包括一個事件傳播體系結構,允許對場景中的專案進行精確的雙精度互動。專案可以處理按鍵事件、滑鼠按下、移動、釋放和雙擊事件,還可以跟蹤滑鼠移動。
  圖形檢視使用BSP(Binary Space Partitioning,即二進位制空間分割槽)樹提供非常快讀得專案發現,因此,它可以實時現實大型場景,即使有數百萬個專案。
  圖形檢視提供了一種基於專案得模型檢視變成方法,多個檢視可以觀察單個場景,並且場景包含不同幾何圖形的專案。

場景(The Scene)

  QGraphicsScene提供了圖形檢視場景,場景有如下職責:

  • 為管理大量專案(圖元專案)提供快速介面;(實測同一個區域不能重疊多了,繪製會卡頓)
  • 將事件傳播到每個項;
  • 管理專案狀態,如選擇和焦點處理;
  • 提供未轉換的渲染功能;主要用於列印;
      該場景用作QGraphicsItem物件的容器。通過呼叫QGraphicsItem::additem() 將項新增到場景中,然後通過呼叫多個項發現函式之一來檢索項。QGraphicsItem::items()及其過載返回由點、矩形、多邊形或常規向量路徑包含或與之相交的所有項。QGraphicsItem::itemAt()返回特定點的最上面的項。所有專案發現功能都按降序堆疊順序返回專案(即第一個返回的專案是最上面的,最後一個專案是最下面的)。
QGraphicsScene scene;
QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100))
QTransform transform;;
QGraphicsItem *item = scene.itemAt(50, 50, transform);
// item == rect

  QGraphicsScene的事件傳播體系結構安排將場景事件傳遞到專案,並管理專案之間的傳播。如果場景在某個位置接收到滑鼠按下事件,則場景將事件傳遞到該位置的任何專案。
  QGraphicsScene還管理某些項狀態,例如項選擇和焦點。可以通過呼叫QGraphicsScene::setSelectionArea(),傳遞任意形狀來選擇場景中的專案。該功函式還可用作QGraphicsView中橡皮擦的選擇區域。要獲取所有當前選定項的列表,請呼叫QGraphicscene::selecteditems()。QGraphicsScene處理的另一個狀態是項是否具有鍵盤輸入焦點。可以通過呼叫QGraphicScene::setFocusItem()或 QGraphicsItem::setFocus()對項設定焦點,也可以通過呼叫QGraphicscene::focusItem()獲取當前焦點項。
  最後,QGraphicScene允許您通過QGraphicScene::render()函式將部分場景渲染到繪製裝置中。可以“列印”部分了解更多有關此內容的資訊。

檢視(The View)

  QGraphicsView提供了檢視小部件,它可以視覺化場景的內容。可以將多個檢視附加到同一場景中,以便在同一資料集中提供多個視口。檢視小部件是一個滾動區域,並提供滾動條用於在大型場景中導航。要啟用OpenGL支援,可以通過呼叫QGraphicsView::setViewport()將QGLWidget設定為視區。

QGraphicsScene scene;
myPopulateScene(&scene);
QGraphicsView view(&scene);
view.show();

  在將事件傳送到視覺化場景之前,檢視從鍵盤和滑鼠接收輸入事件,並將其轉換為場景事件(在適當的情況下將使用的座標轉換為場景座標)。
  用轉換矩陣QGraphicsView::transform(),檢視可以轉換場景的座標系。這允許高階導航功能,如縮放和旋轉。為了方便起見,qgraphicsView還提供了在檢視和場景座標之間轉換的函式:QGraphicsView::mapToScene()和 QGraphicsView::mapFromScene()。
  在這裡插入圖片描述

專案(The Item):圖形元素

QGraphicsItem是場景中圖形項的基類。圖形檢視為典型形狀提供了幾個標準項,例如矩形(QGraphicsRectItem)、橢圓(QGraphicsEllipsItem)和文字項(QGraphicsTextItem),但在編寫自定義項時,最強大的QGraphicsItem功能可用。除此之外,QGraphicsItem還支援以下功能:

  • 滑鼠按下、移動、釋放和雙擊事件,以及滑鼠懸停事件、滾輪事件和上下文選單事件;
  • 鍵盤輸入焦點和按鍵事件;
  • 拖放;
  • 分組,通過父子關係,通過QGraphicsItemGroup;
  • 碰撞檢測;

  專案位於本地座標系中,與QGraphicsView類似,它還提供許多功能,用於在專案和場景之間以及從專案到專案之間對映座標。此外,與QGraphicsView一樣,它可以使用矩陣:QGraphicsItem::Transform()轉換其座標系。這對於旋轉和縮放單個專案很有用。
  項可以包含其他項(子項)。父項的轉換由其所有子項繼承。但是,不管一個項的累積轉換如何,它的所有函式(例如,QGraphicsItem::contains()、QGraphicsItem::boundingRect()、QGraphicsItem::collectsWith() 仍在本地座標中操作。
  QGraphicsItem支援通過QGraphicsItem::shape()函式和QGraphicsItem::collipswith() 進行衝突檢測,這兩個函式都是虛擬函式。通過從QGraphicsItem::shape() 中返回專案的形狀作為本地座標QPaineterPath,QGraphicsItem將為您處理所有衝突檢測。但是,如果您希望提供自己的碰撞檢測,則可以重新實現QGraphicsItem::CollipsWith()。
  在這裡插入圖片描述

Qt圖形檢視框架中的類

  這些類為建立互動式應用程式提供了一個框架。
  在這裡插入圖片描述

 

圖形檢視座標系

  圖形檢視基於笛卡爾座標系;場景中專案的位置和幾何圖形由兩組數字表示:X座標和Y座標。使用未轉換檢視觀察場景時,場景中的一個單元由螢幕上的一個畫素表示。
  注意:由於圖形檢視使用qt座標系,因此不支援倒Y軸座標系(Y向上增長)。
  圖形檢視中有三個有效的座標系**:專案座標、場景座標和檢視座標**。為了簡化實現,圖形檢視提供了方便的功能,允許您在三個座標系之間進行對映。
  渲染時,圖形檢視的場景座標對應於QPainer的邏輯座標,檢視座標與裝置座標相同。後續會說明邏輯座標和裝置座標之間的關係。
  在這裡插入圖片描述

專案座標

  專案在自己的本地座標系中。它們的座標通常以中心點(0,0)為中心,這也是所有變換的中心。專案座標系中的幾何基元通常稱為專案點、專案線或專案矩形。
  在建立自定義項時,只需要擔心項座標;QGraphicsScene和QGraphicsView將為您執行所有轉換。這使得實現自定義項非常容易。例如,如果收到一個滑鼠按下或拖動輸入事件,則事件位置在專案座標中給出。QGraphicsItem::contains()虛擬函式,如果某個點在項中,則返回true,否則返回false,在項座標中接受一個點引數。類似地,項的邊界矩形和形狀位於項座標中。
  在專案的位置是專案中心點在其父座標系中的座標;有時稱為父座標。在這個意義上,場景被視為所有無父項的“父項”。頂層專案的位置在場景座標中。
  子座標是相對於父座標的。如果子座標未轉換,則子座標和父座標之間的差異與父座標中專案之間的距離相同。例如:如果未轉換的子項精確定位在其父項的中心點,則兩個項的座標系將相同。但是,如果子物件的位置是(10,0),子物件的(0,10)點將對應於其父物件的(10,10)點。
  因為項的位置和轉換是相對於父項的,所以子項的座標不受父項的轉換的影響,儘管父項的轉換隱式轉換子項。在上面的例子中,即使父物件被旋轉和縮放,子物件的(0,10)點仍然對應於父物件的(10,10)點。但是,相對於場景,子物件將遵循父物件的變換和位置。如果縮放父物件(2x,2x),子物件的位置將位於場景座標(20,0),其(10,0)點將對應於場景上的點(40,0)。
  由於QGraphicsItem::pos()是少數例外之一,因此QGraphicsItem的函式在項座標中操作,而不考慮項或其任何父項的轉換。例如,專案的邊界矩形(即QGraphicsItem::boundingRect())總是在專案座標中給出。

場景座標

  場景表示其所有項的基礎座標系。場景座標系描述了每個頂層專案的位置,也構成了從檢視傳遞到場景的所有場景事件的基礎。場景中的每個專案都有一個場景位置和邊界矩形(QGraphicsItem::scenePos()和  QGraphicsItem::sceneBoundingRect()),除了其本地項pos和邊界矩形之外。場景位置描述了專案在場景座標中的位置,其場景邊界矩形構成了QGraphicsScene如何確定場景的哪些區域已更改的基礎。場景中的更改通過QGraphicsScene::changed()訊號進行通訊,引數是場景矩形的列表。

檢視座標

  檢視座標是小部件的座標。檢視座標中的每個單元對應一個畫素。這個座標系的特殊之處在於它相對於小部件或視區,並且不受觀察到的場景的影響。QGraphicsView的視區的左上角始終是(0,0),右下角始終是(視區寬度,視區高度)。所有滑鼠事件和拖放事件最初都作為檢視座標接收,您需要將這些座標對映到場景,以便與專案互動。

座標對映

  在處理場景中的專案時,通常可以將座標和任意形狀從場景對映到專案、從專案對映到專案或從檢視對映到場景。例如,在QGraphicsView的視區中單擊滑鼠時,可以通過呼叫QGraphicsView::mapToScene(),然後呼叫QGraphicsScene::ItemAt()來詢問場景游標下的專案。如果要知道某個項在視區中的位置,可以對該項呼叫QGraphicsItem::MapToScene(),然後在檢視上呼叫QGraphicsView::MapFromSecene()。最後,如果要查詢檢視橢圓中的專案,可以將QPaineterPath傳遞給mapToScene(),然後將對映的路徑傳遞給QGraphicScene::items()。
  通過呼叫QGraphicsItem::MapToScene()和QGraphicsItem::mapFromScene(),可以將座標和形狀對映到項的場景或從中對映。還可以通過呼叫QGraphicsItem::mapTopParent()和qgraphicsItem::mapFromParent()對映到項的父項,或者通過呼叫QGraphicsItem::MapToItem()和QGraphicsItem::mapFromItem()在項之間對映。所有對映函式都可以對映點、矩形、多邊形和路徑。
  檢視中有相同的對映函式,可用於對映到場景或從場景對映到場景。QGraphicsView::mapFromSecene()和QGraphicsView::mapToScene()。要從檢視對映到專案,首先對映到場景,然後從場景對映到專案。

 

關鍵特徵

縮放和旋轉

  QGraphicsView支援與QPainer通過QGraphicsView::setMatrix()進行的相同的仿射轉換。通過對檢視應用轉換,您可以輕鬆地新增對常見導航功能(如縮放和旋轉)的支援。
以下是如何在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。
  轉換檢視時,QGraphicsView保持檢視中心對齊。
  有關如何實現基本縮放功能的程式碼,後續會有示例描述。

專案組

  通過使一個專案成為另一個專案的子專案,您可以實現專案分組最基本的特性:

  • 專案將一起移動
  • 所有轉換都從父專案傳播到子專案。

  此外,QGraphicsItemGroup是一個特殊的項,它將子事件處理與用於向組中新增和刪除項的有用介面結合在一起。將項新增到QGraphicsItemGroup將保留該項的原始位置和轉換,而通常重新設定項將導致子項相對於其新父項重新定位自身。為了方便起見,可以通過呼叫QGraphicScene::CreateItemGroup()通過場景建立QGraphicsItemGroups。

小部件和佈局

Qt4.4通過QGraphicsWidget引入了對幾何和佈局感知項的支援。這個特殊的基項類似於QWidget,但與QWidget不同,它不是從QPaintDevice繼承的,而是從QGraphicsItem繼承的。這允許您編寫帶有事件、訊號和槽、大小提示和策略的完整小部件,還可以通過QGraphicsLinearLayout和QGraphicsGridLayout在佈局中管理小部件的幾何圖形。

QGraphicsWidget

  基於QGraphicsItem的功能和精簡的佔地面積,QGraphicsWidget提供了兩個方面的最佳功能:QWidget的額外功能,例如樣式、字型、調色盤、佈局方向及其幾何圖形,以及QGraphicsItem的解析度獨立性和轉換支援。因為圖形檢視使用實座標而不是整數,所以QGraphicsWidget的幾何函式也在QRectF和QPointF上執行。這也適用於框架矩形、邊距和間距。例如,對於QGraphicsWidget,指定內容頁邊距(0.5、0.5、0.5、0.5)並不少見。您可以建立子視窗和“頂級”視窗;在某些情況下,您現在可以為高階MDI應用程式使用圖形檢視。
  一些QWidget的屬性是受支援的,包括視窗標誌和屬性,但不是全部。參考QGraphicsWidget的類文件,以全面瞭解什麼是受支援的,什麼是不受支援的。例如,可以通過將Qt::window標誌傳遞給QGraphicsWidget的建構函式來建立裝飾視窗,但圖形檢視當前不支援MacOs上常見的Qt::Sheet和Qt:: Drawer標誌。

QGraphicsLayout

  QGraphicsLayout是專門為QGraphicsWidget設計的第二代佈局框架的一部分。它的API與QLayout非常相似。您可以在QGraphicsLinearLayout和QGraphicsGridLayout中管理小部件和子佈局。您還可以通過自己對QGraphicsLayout子類化來輕鬆地編寫自己的佈局,或者通過編寫QGraphicsLayoutItem的介面卡子類,將自己的QGraphicsItem項新增到佈局中。

嵌入式小部件支援

  圖形檢視為在場景中嵌入任何小部件提供無縫支援。您可以嵌入簡單的小部件,如QLineEdit或QPushButton,複雜的小部件,如QTabWidget,甚至完整的主視窗。要將小部件嵌入到場景中,只需呼叫QGraphicScene::AddWidget(),或建立QGraphicsProxyWidget例項手動嵌入小部件。
  通過QGraphicsProxyWidget,圖形檢視能夠深入整合客戶端小部件的功能,包括其游標、工具提示、滑鼠、平板電腦和鍵盤事件、子小部件、動畫、彈出視窗(如QComboBox或QCompeter),以及小部件的輸入焦點和啟用。QGraphicsProxyWidget甚至整合了嵌入式小部件的選項卡順序,這樣您就可以在嵌入式小部件中插入和取出選項卡。甚至可以將新的QGraphicsView嵌入到場景中,以提供複雜的巢狀場景。
  當轉換嵌入的小部件時,圖形檢視確保小部件獨立地轉換解析度,允許字型和樣式在放大時保持清晰。(請注意,解析度獨立性的效果取決於樣式。)

 

效能

浮點指令

  為了準確、快速地對專案應用轉換和效果,在假設使用者的硬體能夠為浮點指令提供合理效能的前提下,構建了圖形檢視。
  許多工作站和臺式計算機都配備了適當的硬體來加速這種計算,但是一些嵌入式裝置可能只提供庫來處理數學運算或模擬軟體中的浮點指令。
  因此,某些型別的影響在某些裝置上可能比預期的慢。可以通過在其他區域進行優化來補償這種效能損失;例如,使用OpenGL渲染場景。但是,如果這些優化還依賴於浮點硬體的存在,那麼它們本身可能會導致效能降低。

 
 

相關文章