在第一篇博客中,我們已經完成了 PyQtNode Editor 的基礎環境搭建,并深入解析了自定義圖形場景QDMGraphicsScene的實現原理。那個帶有網格背景的場景就像一張空白的圖紙,現在我們要在這張圖紙上開始繪制真正的節點系統。
今天我們將聚焦于節點編輯器的核心數據結構設計,實現 “節點類” 與 “圖形節點類” 的分離,并完成第一個可交互節點的創建。這一步是整個編輯器的骨架,就像建造房屋時搭建承重結構一樣關鍵。
一、自定義可視化視圖函數
創建一個node_graphic_view.py文件
在 PyQtNode Editor 的開發過程中,圖形視圖的設置對于用戶最終看到的界面效果和操作體驗至關重要。接下來,我們深入解析QDMGraphicsView類的代碼,看看它是如何定制圖形場景的顯示與交互的。
導入必要的模塊
from PyQt5.QtWidgets import QGraphicsView?
from PyQt5.QtCore import *?
from PyQt5.QtGui import *
from PyQt5.QtWidgets import QGraphicsView:從PyQt5.QtWidgets模塊中導入QGraphicsView類。QGraphicsView是 PyQt5 中用于顯示QGraphicsScene(圖形場景)的視圖類,它就像是一個 “畫框”,可以將在場景中繪制的圖形、節點等內容展示出來,并且提供了縮放、滾動等與圖形交互的功能基礎。?
from PyQt5.QtCore import *:導入PyQt5.QtCore模塊中的所有內容。這個模塊包含了 PyQt5 的核心功能,例如信號與槽機制、定時器、元對象系統等,這些功能為圖形視圖的事件處理、狀態管理等提供底層支持 。?
from PyQt5.QtGui import *:導入PyQt5.QtGui模塊中的所有內容。該模塊主要用于處理圖形相關的操作,比如繪制圖形、設置畫筆和畫刷樣式、處理字體等,是實現圖形視圖美觀顯示效果的關鍵。
定義 QDMGraphicsView 類
class QDMGraphicsView(QGraphicsView):
這里定義了一個名為QDMGraphicsView的類,它繼承自QGraphicsView。繼承的作用在于,QDMGraphicsView類可以復用QGraphicsView類已有的功能,同時在此基礎上添加或修改特定的功能,以滿足 PyQtNode Editor 項目中對于圖形視圖的個性化需求。
、
def __init__(self, grScene, parent=None):?super().__init__(parent)?self.grScene = grScene?
?self.initUI()?
?self.setScene(self.grScene)
super().init(parent):調用父類QGraphicsView的初始化方法,確保父類的屬性和行為得到正確的初始化,就像建造房子時先搭建好基本的框架結構。?
self.grScene = grScene:將傳入的圖形場景對象grScene賦值給當前類的實例屬性self.grScene。這樣,QDMGraphicsView類的實例就與特定的圖形場景建立了關聯,后續視圖展示的內容就是這個場景中的元素。?
self.initUI():調用自定義的initUI方法,用于對圖形視圖進行一些個性化的設置,比如渲染效果、滾動條策略等。?
self.setScene(self.grScene):將之前保存的圖形場景對象self.grScene設置為當前圖形視圖要顯示的場景。這一步就像是把一幅畫放入畫框中,圖形視圖會將場景中的圖形、節點等內容展示出來供用戶查看和交互。
def initUI(self):self.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform):通過setRenderHints方法設置圖形渲染的提示選項。這里使用了按位或操作組合了多個渲染提示:?
QPainter.Antialiasing:啟用抗鋸齒功能,使繪制的圖形邊緣更加平滑,避免出現鋸齒狀。?
QPainter.HighQualityAntialiasing:進一步提高抗鋸齒的質量,讓圖形看起來更加精美。?
QPainter.TextAntialiasing:對文本進行抗鋸齒處理,保證顯示的文字清晰、美觀。?
QPainter.SmoothPixmapTransform:使圖像在縮放或變換時更加平滑,避免出現模糊或失真的情況。?
self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate):使用setViewportUpdateMode方法設置視圖端口的更新模式為QGraphicsView.FullViewportUpdate。這意味著每當場景發生變化時,整個視圖端口都會被更新。雖然這種方式在性能上可能不如其他更精細的更新模式,但可以確保視圖顯示的內容始終是最新和完整的。?
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)和self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff):分別設置水平和垂直滾動條的策略為Qt.ScrollBarAlwaysOff,即始終隱藏滾動條。這表明在當前的設計中,不希望用戶通過滾動條來滾動視圖,可能是因為場景的尺寸設置以及整體交互設計不需要滾動條,或者后續會通過其他方式(如鼠標滾輪縮放等)來實現對場景的瀏覽。
完整代碼node_graphic_view.py
# 導入PyQt5的QGraphicsView類,用于顯示和操作QGraphicsScene中的內容
from PyQt5.QtWidgets import QGraphicsView
# 導入PyQt5的核心模塊,包含信號與槽、事件系統等基礎功能
from PyQt5.QtCore import *
# 導入PyQt5的GUI模塊,包含繪圖、字體、顏色等圖形相關功能
from PyQt5.QtGui import *# 自定義圖形視圖類,繼承自QGraphicsView,用于顯示和操作節點編輯器的圖形場景
class QDMGraphicsView(QGraphicsView):# 類的構造函數,接收圖形場景對象和可選的父對象def __init__(self, grScene, parent=None):# 調用父類的構造函數完成初始化super().__init__(parent)# 保存傳入的圖形場景對象的引用self.grScene = grScene# 初始化用戶界面設置self.initUI()# 將圖形場景設置到視圖中,使視圖顯示該場景的內容self.setScene(self.grScene)# 初始化用戶界面的方法,設置視圖的各種屬性和行為def initUI(self):# 設置渲染提示,啟用多項抗鋸齒和高質量渲染選項:# - Antialiasing:平滑圖形邊緣,減少鋸齒# - HighQualityAntialiasing:使用更高質量的抗鋸齒算法# - TextAntialiasing:平滑文本邊緣,提高可讀性# - SmoothPixmapTransform:平滑處理縮放和變換后的像素圖self.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)# 設置視圖更新模式為完全更新,每次場景變化時重繪整個視圖# 這種模式確保顯示效果一致,但可能影響性能self.setViewportUpdateMode(QGraphicsView.FullViewportUpdate)# 設置水平滾動條策略為始終關閉,不顯示水平滾動條self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)# 設置垂直滾動條策略為始終關閉,不顯示垂直滾動條self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
二、調用自定義視圖函數
回到node_graphic_wnd.py文件
導入我們自定義的畫布樣式:
from node_graphics_view import QDMGraphicsView
然后對原來系統的標準視圖更改成我們自定義的視圖:
這個是原來的
self.view = QGraphicsView(self)
self.view.setScene(self.grScene)
更改后的:
self.view = QDMGraphicsView(self.grScene, self)
然后添加一個addDebugContent()方法向場景中添加了多種圖形元素用于測試:
def addDebugContent(self):# 創建綠色畫刷和黑色輪廓畫筆greenBrush = QBrush(Qt.green)outlinePen = QPen(Qt.black)outlinePen.setWidth(2)# 添加可移動的矩形rect = self.grScene.addRect(-100, -100, 80, 100, outlinePen, greenBrush)rect.setFlag(QGraphicsItem.ItemIsMovable)# 添加可選擇和移動的文本text = self.grScene.addText("This is my Awesome text!", QFont("Ubuntu"))text.setFlag(QGraphicsItem.ItemIsSelectable)text.setFlag(QGraphicsItem.ItemIsMovable)text.setDefaultTextColor(QColor.fromRgbF(1.0, 1.0, 1.0))# 添加可移動的按鈕控件widget1 = QPushButton("Hello World")proxy1 = self.grScene.addWidget(widget1)proxy1.setFlag(QGraphicsItem.ItemIsMovable)proxy1.setPos(0, 30)# 添加可選擇的文本編輯控件widget2 = QTextEdit()proxy2 = self.grScene.addWidget(widget2)proxy2.setFlag(QGraphicsItem.ItemIsSelectable)proxy2.setPos(0, 60)# 添加可選擇和移動的線條line = self.grScene.addLine(-200, -200, 400, -100, outlinePen)line.setFlag(QGraphicsItem.ItemIsMovable)line.setFlag(QGraphicsItem.ItemIsSelectable)
最終完整的node_graphic_wnd.py文件
# 從PyQt5的QtWidgets模塊導入所有的類和函數,該模塊包含各種用于創建用戶界面的組件,如窗口、按鈕、布局等
from PyQt5.QtWidgets import *
# 從PyQt5的QtGui模塊導入所有的類和函數,此模塊用于處理圖形相關操作,如畫筆、畫刷、字體、繪圖等功能
from PyQt5.QtGui import *
# 從PyQt5的QtCore模塊導入所有的類和函數,該模塊提供了PyQt5的核心功能,包括信號與槽機制、事件循環、定時器等
from PyQt5.QtCore import *# 從自定義模塊node_graphics_scene中導入QDMGraphicsScene類,該類用于創建自定義的圖形場景
from node_graphics_scene import QDMGraphicsScene