文章目录
继续学习 构建拖拽功能,这是类似 Visio 的核心功能,接下来学习如何实现 拖拽组件、连线功能 和 自由画布设计。
第 3 步:实现拖拽功能
3.1 拖拽的基本概念
在 PyQt 中,可以通过 QGraphicsView
、QGraphicsScene
和 QGraphicsItem
来实现拖拽和自由画布操作:
- QGraphicsView:可视化窗口,用来显示画布。
- QGraphicsScene:管理画布上的所有元素(图形、线条等)。
- QGraphicsItem:画布上的每个图形元素(比如矩形、圆形、图片等),支持拖拽。
3.2 创建基础拖拽界面
我们先从简单的拖拽矩形开始。
代码示例:拖拽矩形
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsRectItem
from PyQt6.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("拖拽矩形示例")
self.setGeometry(100, 100, 800, 600)
# 创建场景和视图
self.scene = QGraphicsScene() # 画布
self.view = QGraphicsView(self.scene, self) # 显示画布
self.setCentralWidget(self.view)
# 添加矩形图形项
rect = QGraphicsRectItem(0, 0, 100, 100) # 创建一个矩形
rect.setBrush(Qt.GlobalColor.blue) # 设置填充颜色
rect.setFlag(QGraphicsRectItem.GraphicsItemFlag.ItemIsMovable) # 设置可拖动
self.scene.addItem(rect) # 添加到画布中
# 创建应用程序
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
运行结果:
- 窗口中会显示一个矩形,用户可以用鼠标拖动它。
3.3 添加多个拖拽元素
现在,我们在画布上添加多个拖拽组件(矩形、圆形等),并为它们设置不同的颜色和大小。
代码示例:多个拖拽元素
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsRectItem, QGraphicsEllipseItem
from PyQt6.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("多个拖拽元素")
self.setGeometry(100, 100, 800, 600)
# 创建场景和视图
self.scene = QGraphicsScene()
self.view = QGraphicsView(self.scene, self)
self.setCentralWidget(self.view)
# 添加矩形
rect = QGraphicsRectItem(0, 0, 100, 100)
rect.setBrush(Qt.GlobalColor.blue)
rect.setFlag(QGraphicsRectItem.GraphicsItemFlag.ItemIsMovable)
self.scene.addItem(rect)
# 添加圆形
circle = QGraphicsEllipseItem(150, 150, 100, 100) # 圆形
circle.setBrush(Qt.GlobalColor.green)
circle.setFlag(QGraphicsEllipseItem.GraphicsItemFlag.ItemIsMovable)
self.scene.addItem(circle)
# 添加另一个矩形
rect2 = QGraphicsRectItem(300, 100, 150, 50)
rect2.setBrush(Qt.GlobalColor.red)
rect2.setFlag(QGraphicsRectItem.GraphicsItemFlag.ItemIsMovable)
self.scene.addItem(rect2)
# 创建应用程序
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
运行结果:
- 画布上会显示三个图形:一个蓝色矩形、一个绿色圆形、一个红色矩形。
- 用户可以用鼠标拖动这些元素到任意位置。
3.4 添加工具箱
我们现在为界面添加一个简单的工具箱,允许用户从工具箱中拖拽组件到画布。
代码示例:工具箱 + 拖拽
import sys
from PyQt6.QtWidgets import (
QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsRectItem,
QDockWidget, QListWidget, QListWidgetItem
)
from PyQt6.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("工具箱 + 拖拽")
self.setGeometry(100, 100, 800, 600)
# 创建场景和视图
self.scene = QGraphicsScene()
self.view = QGraphicsView(self.scene, self)
self.setCentralWidget(self.view)
# 创建工具箱
self.toolbox = QDockWidget("工具箱", self)
self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.toolbox)
# 工具箱内容:列表
self.list_widget = QListWidget()
self.toolbox.setWidget(self.list_widget)
# 添加工具箱选项
for shape in ["矩形", "圆形"]:
item = QListWidgetItem(shape)
self.list_widget.addItem(item)
# 连接工具箱事件
self.list_widget.itemClicked.connect(self.add_item_to_scene)
def add_item_to_scene(self, item):
"""根据工具箱选项在画布上添加图形"""
if item.text() == "矩形":
rect = QGraphicsRectItem(0, 0, 100, 100)
rect.setBrush(Qt.GlobalColor.blue)
rect.setFlag(QGraphicsRectItem.GraphicsItemFlag.ItemIsMovable)
self.scene.addItem(rect)
elif item.text() == "圆形":
circle = QGraphicsEllipseItem(0, 0, 100, 100)
circle.setBrush(Qt.GlobalColor.green)
circle.setFlag(QGraphicsEllipseItem.GraphicsItemFlag.ItemIsMovable)
self.scene.addItem(circle)
# 创建应用程序
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
运行结果:
- 左侧是一个工具箱,包含 “矩形” 和 “圆形” 选项。
- 点击工具箱中的选项,图形会出现在画布上,并且可以拖拽到任意位置。
3.5 画布缩放和平移
为了让用户能够更方便地操作画布,我们添加画布的缩放和平移功能。
代码示例:缩放和平移画布
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsRectItem
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QWheelEvent
class CustomGraphicsView(QGraphicsView):
def __init__(self, scene):
super().__init__(scene)
def wheelEvent(self, event: QWheelEvent):
"""鼠标滚轮缩放画布"""
zoom_factor = 1.15
if event.angleDelta().y() > 0:
self.scale(zoom_factor, zoom_factor) # 放大
else:
self.scale(1 / zoom_factor, 1 / zoom_factor) # 缩小
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("画布缩放和平移")
self.setGeometry(100, 100, 800, 600)
# 创建场景和自定义视图
self.scene = QGraphicsScene()
self.view = CustomGraphicsView(self.scene)
self.setCentralWidget(self.view)
# 添加一个矩形
rect = QGraphicsRectItem(0, 0, 100, 100)
rect.setBrush(Qt.GlobalColor.blue)
rect.setFlag(QGraphicsRectItem.GraphicsItemFlag.ItemIsMovable)
self.scene.addItem(rect)
# 创建应用程序
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
运行结果:
- 用户可以用鼠标滚轮缩放画布。
- 元素依然可以拖拽,画布整体可缩放。
下一步计划
现在已经完成了:
- 拖拽组件到画布。
- 工具箱功能。
- 画布缩放和平移。
接下来,将学习如何 实现连线功能,用于连接画布上的不同组件(类似 Visio 的箭头连接功能)。