使用 PyQtGraph 实现图形连接器:支持动态拖动和箭头连线
引言
在这篇博客中,使用 PyQtGraph 和 PyQt6 创建一个类似 Visio 的图形编辑器,支持拖动图形、添加矩形和椭圆,以及通过箭头动态连线的功能。
功能总结:
- 支持添加矩形和椭圆图形。
- 图形可通过鼠标拖动,并动态更新连接的箭头。
- 支持 “移动模式” 和 “连线模式” 的切换。
- 箭头连线具有真实的起点和终点交点计算。
实现功能的关键点
在实现中,我们利用 PyQtGraph 提供的 GraphicsScene
和 GraphicsView
作为画布,并结合 PyQt5 的 QGraphicsItem
类自定义了以下组件:
DraggableRect
和DraggableEllipse
:分别实现了可拖动的矩形和椭圆。ArrowLine
:支持动态位置更新的箭头连线。- 模式管理:通过按钮切换图形的移动和连线模式。
代码实现
以下是完整代码:
import pyqtgraph as pg
from pyqtgraph.Qt import QtWidgets, QtGui, QtCore
import math
# 可拖动的矩形类
class DraggableRect(QtWidgets.QGraphicsRectItem):
def __init__(self, x, y, w, h, color):
super().__init__(x, y, w, h)
self.setBrush(QtGui.QBrush(color))
self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges)
self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable)
self.connections = []
self.move_enabled = True
def itemChange(self, change, value):
if change == QtWidgets.QGraphicsItem.GraphicsItemChange.ItemPositionChange:
if self.move_enabled:
for arrow in self.connections:
arrow.update_position()
else:
return self.pos()
return super().itemChange(change, value)
def set_movable(self, movable):
self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable, movable)
self.move_enabled = movable
# 可拖动的椭圆类
class DraggableEllipse(QtWidgets.QGraphicsEllipseItem):
def __init__(self, x, y, w, h, color):
super().__init__(x, y, w, h)
self.setBrush(QtGui.QBrush(color))
self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges)
self.setFlag(QtWidgets.QGraphicsItem.GraphicsItemFlag.ItemIsMovable)
self.connections = []
self.move_enabled = True
def itemChange(self, change, value):
if change == QtWidgets.QGraphicsItem.GraphicsItemChange.ItemPositionChange:
if self.move_enabled:
for arrow in self.connections:
arrow.update_position()