Qt 之 Graphics View Framework 簡介


Graphics View Framework

交互式 2D 圖形的 Graphics View 框架概述。自 Qt4.2 中引入了 Graphics View,以取代其前身 QCanvas。Graphics View 提供了一個用於管理和交互大量的可定制的 2D 圖形項與用於可視化這些項的 View 小部件的 surface(曲面),並提供縮放(zooming)和旋轉(rotation)功能支持。

該框架包括事件傳播體系結構(an event propagation architecture),該體系結構允許對場景中的項目進行精確的雙精度交互功能。圖元可以被如下操作處理:按鍵事件,鼠標按下,移動,釋放和雙擊事件,它們還可以跟蹤鼠標的移動。

Graphics View 使用 BSP(Binary Space Partitioning,二進制空間分區)樹提供了非常快速的圖元發現功能,因此,它可以實時可視化大型場景(甚至可以包含數百萬個圖元)。下面列出 Graphics View Framework 的常用模塊:

graph LR subgraph Graphics W[QtCore.QObject] --> F(QtWidgets.QGraphicsObject) F --> S(QtWidgets.QGraphicsTextItem) end subgraph View BB[QtWidgets.QGraphicsLayoutItem] --> AA A[QtGui.QPaintDevice] --> B(QtWidgets.QWidget) B --> C(QtWidgets.QFrame) WW --> FF(QtWidgets.QGraphicsItemGroup) WW -->3F(QtWidgets.QGraphicsLineItem) WW --> 4F(QtWidgets.QGraphicsPixmapItem) W --> B WW --> F(QtWidgets.QGraphicsObject) F --> AA(QtWidgets.QGraphicsWidget) end subgraph Graphics AA --> AAA(QtCharts.QChart) C --> D(QtWidgets.QAbstractScrollArea) D -->E(QtWidgets.QGraphicsView) W --> U(QtWidgets.QGraphicsScene) end subgraph Shape WW[QtWidgets.QGraphicsItem] --> EE(QtWidgets.QAbstractGraphicsShapeItem) EE --> QQ(QtWidgets.QGraphicsEllipseItem) EE --> 3Q(QtWidgets.QGraphicsPathItem) EE --> 4Q(QtWidgets.QGraphicsPolygonItem) EE --> 5Q(QtWidgets.QGraphicsRectItem) EE --> 6Q(QtWidgets.QGraphicsSimpleTextItem) end

1 The Graphics View Architecture

Graphics View 提供了一種基於項目(item-based)的方法來進行模型-視圖編程(model-view programming),非常類似於 InterView 的便利類 QTableView,QTreeView 和 QListView。多個視圖可以觀察單個場景,並且該場景包含各種幾何形狀的圖元項目。

1.1 The Scene

QtWidgets.QGraphicsScene 提供了 Graphics View 場景。QGraphicsScene 類提供了一個用於管理大量 2D 圖形項目的容器(surface)。

場景具有如下功能:

  • 提供用於管理大量圖元項目的快速界面
  • 將事件傳播到每個圖元項目
  • 管理圖元項目狀態,例如選擇和焦點處理
  • 提供未被轉換的渲染功能;主要用於印刷

場景用作 QtWidgets.QGraphicsItem 對象的容器。它與 QtWidgets.QGraphicsView 一起用於可視化 2D 曲面上(2D surface)的圖形項目,例如線條,矩形,文本,甚至是自定義項目。通過調用 addItem() 將圖元項目添加到場景中,然后通過調用許多項目查找功能之一來檢索項目。

請注意,QGraphicsScene 沒有自己的視覺外觀。它只管理圖元項目。您需要創建一個 QGraphicsView 小部件以可視化場景。

要將項目添加到場景,首先需要構造一個 QGraphicsScene 對象。然后,您有兩個選擇:通過調用 addItem() 添加現有的 QGraphicsItem 對象,或者可以調用下列便捷函數之一 addEllipse()addLine()addPath()addPixmap()addPolygon()addRect()addText(),它們都返回一個指向新添加項目的指針。使用這些函數添加的圖元的維度是相對於圖元(item)的坐標系的,並且圖元的位置在場景中被初始化為 \((0,0)\)

您可以使用 QGraphicsView 可視化場景。當場景發生變化時(例如,當某項移動或變換時),QGraphicsScene 發出 change() 信號。要刪除項目,請調用 removeItem()

QGraphicsScene 使用索引算法來有效地管理項目的位置。默認情況下,使用 BSP(二進制空間分區)樹;一種適用於大型場景的算法,其中大多數圖元保持靜止(即不要四處移動)。您可以選擇通過調用 setItemIndexMethod() 禁用此索引。

通過調用 setSceneRect() 設置場景的邊界矩形。可以將圖元項目放置在場景中的任何位置,默認情況下,場景的大小不受限制。場景 rect 僅用於內部簿記,維護場景的圖元項目索引。如果未設置場景矩形,則 QGraphicsScene 將使用 itemsBoundingRect() 返回的所有項目的邊界區域作為場景矩形。但是,itemsBoundingRect() 是一個相對耗時的函數,因為它通過收集場景中每個項目的位置信息進行操作。因此,在大型場景上操作時,應始終設置場景 rect。

QGraphicsScene 的最大優勢之一就是能夠有效確定圖元的位置。即使場景中有數百萬個項目,items() 函數也可以在幾毫秒內確定項目的位置。items() 有多個重載:一個重載在某個位置查找項目,一個重載在多邊形或矩形內部或與之相交,等等。返回的項目列表按堆疊順序排序,最高的項目是列表中的第一項目。為了方便起見,還有一個 itemAt() 函數可在給定位置返回最上面的項目。

QGraphicsScene 還管理某些圖元項目狀態,例如圖元項目選擇和焦點。要選擇項目,請調用 setSelectionArea()(傳遞任意形狀來選擇場景中的項目),並要清除當前選擇,請調用clearSelection()。調用 selectedItems() 以獲取所有選定項的列表。

函數 setSelectionArea() 還用作 QGraphicsView 中橡皮筋選擇的基礎。要獲取所有當前選定項目的列表,請調用 selectedItems() 。QGraphicsScene處理的另一個狀態是項目是否具有鍵盤輸入焦點。您可以通過調用 setFocusItem()setFocus() 來設置焦點,或者通過調用 focusItem() 來獲取當前焦點。

場景的調用方法:

QGraphicsScene(sceneRect[, parent=None])
QGraphicsScene(x, y, width, height[, parent=None])

QGraphicsScene 的另一個職責是傳播來自 QGraphicsView 的事件。要將事件發送到場景,您可以構造一個繼承 QEvent 的事件,然后使用 sendEvent() 進行發送。event() 負責將事件調度到各個圖元項目。一些常見事件由便利事件處理程序處理。例如,按鍵事件由 keyPressEvent() 處理,鼠標按鍵事件由 mousePressEvent() 處理。

按鍵事件將傳遞到焦點圖元項目。要設置焦點圖元項目,可以調用 setFocusItem(),傳遞接受焦點的圖元項目,或者該項目本身可以調用 setFocus()。 調用 focusItem() 以獲取當前的焦點項目。為了與小部件兼容,場景還保留其自己的焦點信息。默認情況下,場景沒有焦點,並且所有按鍵事件都將被丟棄。如果調用 setFocus() 或場景中的某個項目獲得焦點,則場景將自動獲得焦點。如果場景具有焦點,則 hasFocus() 將返回 true,並將按鍵事件轉發到焦點項(如果有)。如果場景失去焦點(例如,有人在某個項目具有焦點時調用 clearFocus()),則場景將保留其項目焦點信息,並且一旦場景重新獲得焦點,它將確保最后一個焦點項目重新獲得焦點。

對於鼠標懸停效果,QGraphicsScene 調度懸停事件。如果某個圖元項目接受懸停事件(請參見acceptHoverEvents()),則當鼠標進入其區域時,它將收到 GraphicsSceneHoverEnter 事件。當鼠標繼續在項目區域內移動時, QGraphicsScene 將向其發送 GraphicsSceneHoverMove 事件。當鼠標離開該項目的區域時,該項目將收到 GraphicsSceneHoverLeave 事件。

所有鼠標事件都會傳遞到當前的鼠標采集器項目。如果一個項目接受鼠標事件(請參見 acceptedMouseButtons() 並且接受鼠標按下,則它將成為場景的鼠標捕獲器。當沒有其他鼠標按鈕被按下時,它會一直停留在鼠標抓取器上,直到釋放鼠標為止。您可以調用 mouseGrabberItem() 來確定當前正在抓住鼠標的圖元項目。

最后,QGraphicsScene 允許您通過 render() 函數將場景的一部分渲染到繪制設備中。

1.2 The View

QGraphicsView 類提供了一個用於顯示 QGraphicsScene 的內容小部件。QGraphicsView 在可滾動視口(viewport)中可視化 QGraphicsScene 的內容。

QGraphicsView 提供了視圖小部件,可將場景的內容可視化。您可以將多個視圖附加到同一場景,以在同一數據集中提供多個視口。視圖窗口小部件是一個滾動區域,並提供用於在大型場景中導航的滾動條。要啟用 OpenGL 支持,可以通過調用 setViewport() 將 QOpenGLWidget 設置為視口。

視圖從鍵盤和鼠標接收輸入事件,然后將其轉換為場景事件(在適當的情況下將其轉換為場景坐標),然后再將事件發送到可視化場景。

使用其變換矩陣 transform(),視圖可以變換場景的坐標系。這允許高級導航功能,例如縮放和旋轉。為了方便起見,QGraphicsView 還提供了用於在視圖和場景坐標之間進行轉換的函數:mapToScene()mapFromScene()

QtWidgets.QGraphicsView 在可滾動 viewport 中可視化 QtWidgets.QGraphicsScene 的內容。

為了使場景可視化,首先要構造一個 QtWidgets.QGraphicsView 對象,然后將要可視化的場景的地址傳遞給 QtWidgets.QGraphicsView 的構造函數。另外,您可以調用 setScene() 在以后設置場景。調用 show() 后,默認情況下,視圖將滾動到場景的中心並顯示此時可見的所有圖元項目。 例如:

scene = QGraphicsScene()
scene.addText("Hello, world!")

# 等價於 QGraphicsView(scene)
view = QGraphicsView()
view.setScene(scene)
view.show()

您可以使用滾動條或調用 centerOn() 顯式滾動到場景中的任何位置。通過將一個點傳遞給 centerOn(),QGraphicsView 將滾動其視口以確保該點在視圖中居中。同時提供了用於滾動到 QGraphicsItem 的重載,在這種情況下,QGraphicsView 將看到項目的中心在視圖中居中。如果只需要確保某個區域可見(但不必居中),則可以調用 sureVisible()

QGraphicsView 可用於可視化整個場景或其中的一部分。默認情況下,第一次顯示視圖時,會自動檢測到可視化區域(通過調用 itemsBoundingRect())。要自己設置可視化區域矩形,可以調用 setSceneRect()。這將適當地調整滾動條的范圍。請注意,盡管場景支持幾乎不受限制的大小,但滾動條的范圍永遠不會超出整數 (INT_MIN, INT_MAX) 的范圍。

QGraphicsScene 還管理某些圖元項目狀態,例如圖元項目選擇和焦點。您可以通過調用 setSelectionArea() 傳遞任意形狀來選擇場景中的項目。此函數還用作 QGraphicsView 中橡皮筋選擇的基礎。要獲取所有當前選定項目的列表,請調用 selectedItems()。 QGraphicsScene 處理的另一個狀態是項目是否具有鍵盤輸入焦點。您可以通過調用 setFocusItem()setFocus() 來設置焦點,或者通過調用 focusItem() 來獲取當前焦點。

QGraphicsView 通過調用 render() 可視化場景。默認情況下,使用常規 QPainter 並使用默認渲染提示將項目繪制到視口上。若要更改繪畫項目時 QGraphicsView 傳遞給 QPainter 的默認渲染提示,可以調用setRenderHints()

默認情況下,QGraphicsView 為視口窗口小部件提供常規 QWidget。您可以通過調用 viewport() 來訪問此小部件,也可以通過調用 setViewport() 來替換它。

要使用 OpenGL 進行渲染,只需調用 setViewport(新的 QOpenGLWidget)。QGraphicsView 擁有視口小部件的所有權。

QGraphicsView 使用 QTransform 支持仿射變換。最常見的兩種轉換是 scaling,用於實現縮放(zooming)和旋轉(rotation)。QGraphicsView 在轉換過程中保持視圖中心不變。由於場景對齊(setAligment()),平移視圖將不會產生視覺影響。您可以將矩陣傳遞給 setTransform(),也可以調用便捷函數之一 rotate()scale()translate()shear()

您可以使用鼠標和鍵盤與場景中的項目進行交互。QGraphicsView 將鼠標和鍵事件轉換為場景事件(繼承 QGraphicsSceneEvent 的事件),並將其轉發到可視化場景。最后,處理事件並對事件做出反應的是獨立項目。例如,如果單擊一個可選擇的項目,則該項目通常會讓場景知道它已被選中,並且它還將重繪自身以顯示選擇矩形。類似地,如果您單擊並拖動鼠標以移動可移動項,則它是處理鼠標移動並自行移動的項。默認情況下,圖形項目互動處於啟用狀態,您可以觸發調用。

您還可以通過創建 QGraphicsView 的子類並重新實現鼠標和鍵事件處理程序來提供自己的自定義場景交互。
為了簡化您如何以編程方式與視圖中的項目進行交互,QGraphicsView 提供了映射函數 mapToScene()mapFromScene() 以及項目訪問器 items()itemAt()。這些功能允許您在視圖坐標和場景坐標之間映射點,矩形,多邊形和路徑,並使用視圖坐標在場景中查找項目。

QtWidgets.QGraphicsView(scene[, parent=None])

  • parent:QWidget
  • scene:QGraphicsScene

1.3 The Item

QGraphicsItem 是場景中圖形項的基類。Graphics View 為典型形狀提供了幾個標准項,例如矩形(QGraphicsRectItem),橢圓(QGraphicsEllipseItem)和文本項(QGraphicsTextItem),但時,最強大的是 QGraphicsItem 可以編寫自定義項。除此之外,QGraphicsItem 支持以下功能:

  • 鼠標按下,移動,釋放和雙擊事件,以及鼠標懸停事件,滾輪事件和上下文菜單事件。
  • 鍵盤輸入焦點和按鍵事件
  • 拖放
  • 通過 parent-child 關系以及 QGraphicsItemGroup 進行分組
  • 碰撞檢測(Collision detection)

圖元項目位於本地坐標系(local coordinate system)中,就像 QGraphicsView 一樣,它還提供了許多功能,用於在項目與場景之間以及項目與項目之間映射坐標。而且,像 QGraphicsView 一樣,它可以使用 matrix:transform() 變換其坐標系。這對於旋轉和縮放單個項目很有用。

項可以包含其他項(子項)。父項的轉換由其所有子項繼承。不過,不管某項的累積轉換如何,它的所有功能(例如,contains(), boundingRect(), QGraphicsItem::collidesWith())都仍在本地坐標下運行。

QGraphicsItem 通過 shape() 函數和 QGraphicsItem::collidesWith() 這兩個虛擬函數都支持沖突檢測。通過從 shape() 返回項目的形狀作為局部坐標 QPainterPath,QGraphicsItem 將為您處理所有碰撞檢測。但是,如果要提供自己的沖突檢測,則可以重新實現 QGraphicsItem::collidesWith()

更多內容見:QtWidgets.QGraphicsItem

QtWidgets.QGraphicsItem 類是 QtWidgets.QGraphicsScene 中所有圖形項的基類。為了方便描述,將 QtWidgets.QGraphicsItem 實例命名為圖元QtWidgets.QGraphicsItem 為編寫您自己的自定義圖元項提供了一個輕量級的基礎。它包括定義圖元項的幾何形狀(geometry),碰撞檢測(collision detection),且有繪畫實現以及通過事件處理程序進行的圖元項交互。

為方便起見,Qt為最常見的形狀提供了一組標准圖形項:

圖元項目的所有幾何信息均基於其本地坐標系(Local Coordinate System)[1]。該圖元項的位置 pos() 是唯一在本地坐標中不起作用的函數,因為它在父坐標中返回一個位置。

您可以通過調用 setVisible() 設置圖元項目是否應可見(即繪制和接受事件)。隱藏圖元項目也會隱藏其子項。同樣,您可以通過調用 setEnabled() 啟用或禁用圖元項目。

如果禁用某個圖元項目,則其所有子項也將被禁用。默認情況下,圖元項目既可見又啟用。若要切換是否選擇圖元項目,請首先通過設置 ItemIsSelectable 標志啟用選擇,然后調用 setSelected()。通常,由於用戶交互,場景(scene)會切換選擇。

要編寫自定義的圖元項目,首先創建 QGraphicsItem 的子類,然后實現其兩個純虛擬公共函數:boundingRect() 返回該圖元項目所繪制區域的估計值,paint() 實現實際繪圖(the actual painting)。例如:

class SimpleItem(QtWidgets.QGraphicsItem):
    def boundingRect(self):
        penWidth = 1.0
        return QtCore.QRectF(-10 - penWidth / 2, -10 - penWidth / 2,
                             20 + penWidth, 20 + penWidth)

    def paint(self, painter, option, widget):
        painter.drawRoundedRect(-10, -10, 20, 20, 5, 5)

boundingRect() 函數有許多不同的用途。QtWidgets.QGraphicsScene 的項目索引基於 boundingRect(),並且 QtWidgets.QGraphicsView 將其用於剔除不可見的項目以及確定繪制重疊項目時需要重新組合的區域。此外,QtWidgets.QGraphicsItem 的碰撞檢測機制使用 boundingRect() 提供有效的截止點(cut-off)。collidesWithItem() 中的細粒度碰撞算法基於調用 shape() 的方法,該方法會返回圖元形狀的精確輪廓作為QtGui.QPainterPath

QtWidgets.QGraphicsScene 期望所有圖元項目的 boundingRect()shape() 保持不變,除非得到通知。如果您想以任何方式更改圖元的幾何形狀,則必須首先調用 prepareGeometryChange() 以允許 QtWidgets.QGraphicsScene 更新其簿記(bookkeeping)。

碰撞檢測可以通過兩種方式完成:

  1. 重新實現 shape() 以為您的圖元返回准確的形狀,並依靠 collidesWithItem() 的默認實現進行形狀與形狀的交點(shape-shape intersection)。如果形狀復雜,這可能代價會非常高。
  2. 重新實現 collidesWithItem() 以提供您自己的自定義圖元項目和形狀碰撞算法。

可以調用 contains() 函數來確定圖元項目是否包含一個點。該函數也可以通過圖元項重新實現。contains() 的默認行為是基於調用 shape() 的。

圖元項目可以包含其他圖元項目,也可以被包含在其他圖元項目中。所有圖元項目都可以有一個父圖元項目和一列子項目。除非該圖元項目沒有父對象,否則它的位置是父對象的坐標(即父對象的本地坐標)。父項將其位置及其變換傳播給所有子項。

1.3.1 Transformations

QtWidgets.QGraphicsItem 除了提供其基本位置 pos() 外,還支持投影變換(projective transformations)。有幾種更改圖元項目變換的方法。對於簡單轉換,可以調用便捷函數 setRotation()setScale(),也可以將任何變換矩陣傳遞給 setTransform()。對於高級轉換控制,您還可以通過調用 setTransformations() 來設置多個組合轉換。

圖元項變換從父項到子項累積,因此,如果父項和子項都旋轉 90 度,則子項的總轉換將為 180 度。同樣,如果項目的父項縮放到其原始大小的 2 倍(2x),則其子項也將擴大兩倍。圖元項的變形不會影響其自身的局部幾何關系( local geometry);所有幾何函數(例如,contains()update() 和所有映射函數)仍在局部坐標(local coordinates)下運行。為方便起見,QtWidgets.QGraphicsItem 提供了一個函數 SceneTransform()(它返回該項的總變換矩陣(包括其位置以及所有父項的位置和變換))和 scenePos()(該函數返回其在場景坐標中的位置)。 要重置圖元的矩陣,請調用 resetTransform()

某些轉換操作根據其應用順序產生不同的結果。例如,如果縮放轉換然后旋轉,則可能會得到與首先旋轉轉換不同的結果。但是,您在 QtWidgets.QGraphicsItem 上設置轉換屬性的順序不會影響最終的轉換。QtWidgets.QGraphicsItem 始終以固定的定義順序應用屬性:

The item’s base transform is applied ( transform() )
The item’s transformations list is applied in order ( transformations() )
The item is rotated relative to its transform origin point ( rotation() , transformOriginPoint() )
The item is scaled relative to its transform origin point ( scale() , transformOriginPoint() )

1.3.2 Painting

QtWidgets.QGraphicsView 調用 paint() 函數來繪制圖元項目的內容。該圖元項目沒有背景或沒有默認填充值;該圖元項目后面的任何內容都會在此功能中未明確繪制的所有區域中 shine。您可以調用 update() 安排重新繪制,可以選擇傳遞需要重新繪制的矩形。根據圖元項目是否在視圖中可見,該項目可能會或可能不會重新粉刷(repaint)。QtWidgets.QGraphicsItem 中沒有等效於 repaint() 的函數。

圖元項目是按視圖繪制的,從父項開始,然后是子項,按升序排列。您可以通過調用 setZValue() 設置圖元的堆疊順序,並通過調用 zValue() 對其進行測試,其中,在 z 值高的圖元之前先繪制 z 值低的圖元。堆疊順序適用於同級圖元;父項總是在子項前被繪制。

1.3.3 Sorting

所有圖元項目均按定義的穩定順序繪制,並且此相同的順序決定了當您單擊場景時哪些項目將首先接收鼠標輸入。通常,您不必擔心排序,因為項目遵循“自然順序”,遵循場景的邏輯結構。

某個圖元項目的子項堆疊在父項的頂部,而同級項則按照插入順序(即,它們被添加到場景或添加到同一父項的順序)堆疊。如果您添加項目 A,然后添加 B,則 B 將位於 A 的頂部。如果您添加 C,則項目的堆疊順序將是 A,然后是 B,然后是 C。

對於高級用戶,有一些方法可以更改項目的排序方式:

  • 您可以在一個圖元項目上調用 setZValue(),以將其顯式堆疊在其他同級項目之上或之下。項的默認 Z 值為 0。具有相同 Z 值的項按插入順序堆疊。
  • 您可以調用 stackBefore() 重新排序子級列表。這將直接修改插入順序。
  • 您可以設置 ItemStacksBehindParent 標志以將子項堆疊在其父項之后。

兩個同級圖元的堆疊順序也計入每個圖元的子代圖元和后代圖元。因此,如果一項在另一項之上,則其所有子項也將在另一項所有子項之上。

1.3.4 Events

QtWidgets.QGraphicsItem 通過虛擬函數 sceneEvent()QtWidgets.QGraphicsScene 接收事件。此函數將最常見的事件分配給一組便捷事件處理程序:

  • contextMenuEvent() handles context menu events
  • focusInEvent() and focusOutEvent() handle focus in and out events
  • hoverEnterEvent() , hoverMoveEvent() , and hoverLeaveEvent() handles hover enter, move and leave events
  • inputMethodEvent() handles input events, for accessibility support
  • keyPressEvent() and keyReleaseEvent() handle key press and release events
  • mousePressEvent() , mouseMoveEvent() , mouseReleaseEvent() , and mouseDoubleClickEvent() handles mouse press, move, release, click and doubleclick events

您可以通過安裝事件過濾器(event filters)來過濾任何其他圖元項目的事件。此功能與 Qt 的常規事件過濾器(請參閱 installEventFilter())分開,后者僅適用於 QObject 的子類。在通過調用 installSceneEventFilter() 將項目安裝為另一個項目的事件過濾器之后,虛擬函數 sceneEventFilter() 會接收到過濾后的事件。您可以通過調用 removeSceneEventFilter() 來刪除項目事件過濾器。

1.3.5 Custom Data

有時,將自定義數據注冊到某個圖元項目(自定義圖元項目或標准圖元項目)很有用。您可以在任何圖元項目上調用 setData(),以使用鍵值對(鍵為整數,並且值為 QVariant)將數據存儲在其中。要從項目中獲取自定義數據,請調用 data()。Qt 本身完全沒有涉及此功能。

1.3.6 QtWidgets.QGraphicsItem 的使用

class QGraphicsItem([parent=None]) 使用給定的父項構造一個 QtWidgets.QGraphicsItem。它不會修改 parent() 返回的父對象。

如果 parentNone,你可以通過調用 addItem() 將圖元項目添加到場景中。該圖元項目將成為頂級圖元項目(top-level item)。

QtWidgets.QGraphicsItem.GraphicsItemFlag:枚舉描述了可以在圖元項目上設置的不同標志,以切換圖元項目行為中的不同功能。

常量 描述
QGraphicsItem.ItemIsMovable 該項目支持使用鼠標進行交互式移動。通過單擊該項目然后拖動,該項目將與鼠標光標一起移動。如果該項目有孩子,則所有孩子也將移動。如果項目是選擇的一部分,則所有選擇的項目也會移動。通過 QtWidgets.QGraphicsItem 的鼠標事件處理程序的基本實現,可以方便地提供此功能。
QGraphicsItem.ItemIsSelectable 該項目支持選擇。啟用此功能將使 setSelected() 可以切換圖元項目的選擇。通過調用 setSelectionArea(),單擊某項或在 QtWidgets.QGraphicsView 中使用橡皮筋選擇,它還將使該項自動被選擇。
QGraphicsItem.ItemIsFocusable 該項目支持鍵盤輸入焦點(即它是一個輸入項目)。啟用此標志將允許該項目接受焦點,這再次允許將鍵事件傳遞到 keyPressEvent()keyReleaseEvent()
QGraphicsItem.ItemClipsToShape 圖元會剪裁成自己的形狀。該項目無法在其形狀之外繪制或接收鼠標,平板電腦,拖放或懸停事件。默認情況下禁用。此行為由 drawItems()drawItems() 強制執行。這個標志是在 Qt 4.3 中引入的。
QGraphicsItem.ItemClipsChildrenToShape 該項將其所有后代的繪畫剪裁成自己的形狀。此項的直接或間接子項不能超出該項目的形狀。默認情況下,此標志為禁用狀態。孩子們可以在任何地方畫畫。此行為由 drawItems()drawItems() 強制執行。 這個標志是在 Qt 4.3 中引入的。

更多 flags 見:QGraphicsItem

1.3.7 QtWidgets.QGraphicsItem.boundingRect()

返回 QRectF。這個純虛函數將圖元項目的外部邊界定義為矩形;所有繪畫都必須限制在圖元項目的邊界區域內。QtWidgets.QGraphicsView 使用它來確定該圖元項目是否需要重繪。盡管圖元項目的形狀可以是任意的,但邊界矩形始終為矩形,並且不受圖元項目變換的影響。

如果要更改圖元項目的邊界矩形,必須首先調用 prepareGeometryChange()。這會通知場景即將發生的更改,以便可以更新其圖元項目幾何索引;否則,場景將不會意識到該圖元的新幾何形狀,並且結果是不確定的(通常,渲染工件( rendering artifacts)保留在視圖(view)中)。

重新實現此功能,以使 QtWidgets.QGraphicsView 決定需要重繪窗口小部件的哪些部分(如果有)。注意:對於繪制輪廓/筆觸的形狀,重要的是在邊界矩形中包括筆寬的一半。但是,沒有必要補償抗鋸齒。

例子:

def boundingRect(self):
    penWidth = 1.0
    return QtCore.QRectF(-radius - penWidth / 2, -radius - penWidth / 2,
                  diameter + penWidth, diameter + penWidth)

更多精彩參考我的另一篇博文:Qt 手冊


  1. 本地坐標系是以物體自身位置作為原點,表示物體間相對位置和方向,並且會根據物體自身旋轉而旋轉。 ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM