仓库地址 https://gitlab.com/pavel.krupala/pyqt-node-editor-tutorials.git
效果图
代码
五- 先来看看 对各种对象的实例化改变:
-
node_editor_wnd.py
四 - 把scene 的实例化 放在了这个文件
- node_scene.py
from node_graphics_scene import QDMGraphicsScene
class Scene():
def __init__(self):
self.nodes = []
self.edges = []
self.scene_width = 64000
self.scene_height = 64000
self.initUI()
def initUI(self):
self.grScene = QDMGraphicsScene(self)
self.grScene.setGrScene(self.scene_width, self.scene_height)
def addNode(self, node):
self.nodes.append(node)
def addEdge(self, edge):
self.edges.append(edge)
def removeNode(self, node):
self.nodes.remove(node)
def removeEdge(self, edge):
self.edges.remove(edge)
-
node_node.py
想要添加一个Node, 就实例化 一个Node类
from node_graphics_node import QDMGraphicsNode
class Node():
"""
node的功能细节.
"""
def __init__(self, scene, title="Undefined Node"):
# 传入scene
self.scene = scene
self.title = title
# node的具体样式细节 由 QDMGraphicsNode 来实现
self.grNode = QDMGraphicsNode(self, self.title)
# self.grNode是你看见的
self.scene.grScene.addItem(self.grNode)
# 用于存放该node的地址
self.scene.addNode(self)
#后续的连接点 , 暂时用不到
self.inputs = []
self.outputs = []
- node_graphics_node.py
node的具体样式细节
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class QDMGraphicsNode(QGraphicsItem):
def __init__(self, node, title='Node Graphics Item', parent=None):
super().__init__(parent)
self._title_color = Qt.white
self._title_font = QFont("Ubuntu", 10)
self.width = 180
self.height = 240
# 圆角尺寸
self.edge_size = 10.0
self.title_height = 24.0
self._padding = 4.0
self._pen_default = QPen(QColor("#7F000000"))
self._pen_selected = QPen(QColor("#FFFFA637"))
self._brush_title = QBrush(QColor("#FF313131"))
self._brush_background = QBrush(QColor("#E3212121"))
self.initTitle()
self.title = title
self.initUI()
def initUI(self):
self.setFlag(QGraphicsItem.ItemIsSelectable)
self.setFlag(QGraphicsItem.ItemIsMovable)
def initTitle(self):
self.title_item = QGraphicsTextItem(self)
self.title_item.setDefaultTextColor(self._title_color)
self.title_item.setFont(self._title_font)
self.title_item.setPos(self._padding, 0)
self.title_item.setTextWidth(
self.width
- 2 * self._padding
)
@property
def title(self): return self._title
@title.setter
def title(self, value):
self._title = value
self.title_item.setPlainText(self._title)
# 这个函数是关键 , 可以当做是 node的paint画布容器;
# 如果没有boundingRect, paint出来的东西是没法操作的
def boundingRect(self):
return QRectF(
0,
0,
2 * self.edge_size + self.width,
2 * self.edge_size + self.height
).normalized()
# paint 只是画给人看的 , 哪怕 没有 paint , boundingRect区域也是存在的.
def paint(self, painter, QStyleOptionGraphicsItem, widget=None):
# title
# `addRoundedRect` 添加圆角, `addRect` 添加矩形
path_title = QPainterPath()
path_title.setFillRule(Qt.WindingFill)
path_title.addRoundedRect(0,0, self.width, self.title_height, self.edge_size, self.edge_size)
path_title.addRect(0, self.title_height - self.edge_size, self.edge_size, self.edge_size)
path_title.addRect(self.width - self.edge_size, self.title_height - self.edge_size, self.edge_size, self.edge_size)
painter.setPen(Qt.NoPen)
painter.setBrush(self._brush_title)
painter.drawPath(path_title.simplified())
# content
path_content = QPainterPath()
path_content.setFillRule(Qt.WindingFill)
path_content.addRoundedRect(0, self.title_height, self.width, self.height - self.title_height, self.edge_size, self.edge_size)
path_content.addRect(0, self.title_height, self.edge_size, self.edge_size)
path_content.addRect(self.width - self.edge_size, self.title_height, self.edge_size, self.edge_size)
painter.setPen(Qt.NoPen)
painter.setBrush(self._brush_background)
painter.drawPath(path_content.simplified())
# outline , 边框颜色 及 被 选中颜色
path_outline = QPainterPath()
path_outline.addRoundedRect(0, 0, self.width, self.height, self.edge_size, self.edge_size)
painter.setPen(self._pen_default if not self.isSelected() else self._pen_selected)
painter.setBrush(Qt.NoBrush)
painter.drawPath(path_outline.simplified())
addRoundedRect
添加圆角, addRect
添加矩形