實戰PyQt5: 082-圖形檢視(Graphics-View)框架簡介

seniorwizard發表於2020-12-04

圖形檢視框架(Graphics View Framework)提供了一個用於管理大量定製2D圖形圖元(Item)並與之互動的表面(surface)。以及一個可用於視覺化這些圖元的檢視(View)部件,它支援縮放和旋轉。

該框架包含一個事件傳播體系結構,該體系結構允許對場景(Scene)中的圖元進行精確的互動。在其中的圖元可以處理按鍵事件,滑鼠按下,移動,釋放和雙擊事件,它們也可以跟蹤滑鼠的移動。框架使用了BSP(Binary Space Partitioning)樹來提供圖元快速發現功能,因此它可以對大型場景進行視覺化。

圖形檢視架構

圖形檢視提供了一種基於圖元的模型檢視處理的方法,類似於Model-View架構中的類QTableView,QTreeView和QListView,多個檢視可以觀察單個場景,並且場景包含各種幾何形狀的圖元。

 

場景(Scene)

QGraphicsScene提供了“圖形檢視”的場景。該場景具有以下功能職責:

  • 提供用於管理大量圖元的快速介面;
  • 將事件傳播到每個圖元;
  • 管理圖元狀態,例如選擇和焦點處理;
  • 提供為進行轉換的渲染功能,主要用於列印輸出。

QGraphicesScene用作QGraphicsItem圖元的容器,通過呼叫QGraphicsScene.addItem()可以將圖元新增到場景中,然後通過呼叫各種圖元發現函式來檢索圖元。QGraphicsScene.items()返回由點,矩形,多邊形或者向量路徑所包含或與之相交的所有圖元。QGraphicsScene.itemAt()返回特定點上的頂層圖元。所有圖元發現函式都以降序堆疊的方式返回圖元(即,第一個返回的圖元是最頂層的,最後一個圖元是最底部的)。

scene =QGraphicsScene()
rect=scene.addRect(QRectF(0,0,100,100))  # 新增一個QGraphicsRectItem
item=scene.itemAt(50, 50, QTransform())   # 返回新增的item

QGraphicsScene的事件傳播體系結構排程場景事件以傳遞給圖元,並管理圖元事件在圖元之間的傳播。如果場景在某個位置收到滑鼠按下事件,那麼場景會將事件傳遞到該位置上的所有圖元。

QGraphicsScene也管理某些圖元狀態,例如圖元選擇和焦點。可以通過呼叫QGraphicsScene.setSelectionArea()設定任意形狀的選擇區間來選擇場景中的圖元。呼叫QGraphicsScene.selectedItems()可以獲得所有當前選定圖元的列表。QGraphicsScene處理的另一個狀態是是否具有鍵盤焦點,可以通過呼叫QGraphicsScene.setFocusItem()或QGraphicsScene.setFocus()來設定圖元的焦點,通過呼叫QGraphicsScene.focusItem()來獲得當前的焦點圖元。

呼叫QGraphicsScene.scene()將場景的一部分渲染到繪製裝置中。

檢視(View)

QGraphicsView提供檢視部件,它可以將場景的內容視覺化。檢視視窗部件是一個可滾動區域,它提供了用於在大型場景中導航的滾動條。如果要啟用OpenGL支援,可以通過呼叫QGraphicsView.setViewport()將QOpenGLWidget物件設定為視口。

scene =QGraphicsScene()
myPopulateScene(scene)
view = QGraphicsView(scene)
view.show()

檢視從鍵盤和滑鼠接收輸入事件,然後將其轉換為場景事件(在適當的情況下將其轉換為場景座標),然後再將事件傳送到視覺化場景。

使用轉換矩陣QGraphicsView.transform(),檢視可以轉換場景的座標,這樣可以實現縮放和旋轉等功能。QGraphicsView還提供了用於檢視和場景座標之間進行轉換的函式:QGraphicsView.mapToScene()和QGraphicsView.mapFromScene()。

實戰PyQt5: 082-圖形檢視(GV)框架簡介

圖片來源(doc.qt.io)

圖元(Item)

QGraphicsItem是場景中圖形圖元的基類。在Qt的圖形檢視框架中提供了幾種典型形狀的標準影像圖元,例如矩形(QGraphicsRectItem),橢圓(QGraphicsEllipseItem)和文字條目(QGraphicsTextItem)。QGraphicsItem支援以下功能:

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

圖元位於區域性座標系統中,像QGraphicsView一樣,它提供了許多用於在圖元與場景之間以及條目與圖元之間對映座標的功能。另外,它可以使用矩陣變換QGraphicsItem.transform()函式變換其座標系,這一點對旋轉和縮放單個圖元時相當有用。

圖元可以包含其他圖元(子圖元)。父圖元的轉換由其所有子圖元繼承。但是,不管圖元的累積轉換如何,它的所有功能(例如, QGraphicsItem.contains(), QGraphicsItem.boundingRect(), QGraphicsItem.collidesWith())仍在區域性座標下執行。

QGraphicsItem支援通過QGraphicsItem.shape()函式和QGraphicsItem.collidesWith()這兩個函式進行衝突檢測。通過從QGraphicsItem.shape()返回專案的形狀作為區域性座標QPainterPath,QGraphicsItem將處理所有碰撞檢測。可以重新實現QGraphicsItem.collidesWith()來提供自己的衝突檢測。

實戰PyQt5: 082-圖形檢視(GV)框架簡介

圖片來源(doc.qt.io)

樣例程式碼

使用QGraphicsScene建立一個場景,使用addLine()新增一條線,addTex()新增文字,addRect()新增一個矩形,addEllipse()新增一個圓。使用QGraphicsRectItem建立一個矩形圖元,並將矩形圖元的邊框顏色設定為紅色,使用setItem()將其新增到場景中。然後使用QGraphicsView建立一個檢視,並將場景顯示出來。完整程式碼如下:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPen,QColor
from PyQt5.QtWidgets import (QApplication, QGraphicsScene, QGraphicsView, QGraphicsRectItem)
                             
if __name__ == '__main__':
    app = QApplication(sys.argv)
    scene = QGraphicsScene()
    
    scene.addLine(20, 20, 200, 200)
    scene.addText('Hello Graphics View')
    scene.addRect(0, 0, 320, 240)
    scene.addEllipse(100, 100, 100, 100)
    
    rect = QGraphicsRectItem(99, 99, 102, 102)
    rect.setPen(QPen(Qt.red))
    scene.addItem(rect)
    
    view = QGraphicsView(scene)
    view.setWindowTitle('實戰PyQt5: 圖形檢視 演示!')
    view.resize(480, 320)
    view.show()
    
    sys.exit(app.exec())

執行結果如下圖:

實戰PyQt5: 082-圖形檢視(GV)框架簡介

Graphics View 簡單示例

本文知識點

  • 圖形檢視框架的基本構成;
  • 場景類QGraphicesScene;
  • 檢視類QGraphicsView;
  • 圖元類QGraphicsItem。

前一篇: 實戰PyQt5: 081-文字瀏覽器QTextBrowser

相關文章