使用PyQt5库创建了一个简单的图形界面,其中包含一个QGraphicsView、QGraphicsScene和自定义的QGraphicsItem(矩形和椭圆)。这些图形项会在窗口中自动移动,并在碰撞时改变颜色。
详细解释:
1. 导入必要的库和模块:
- PyQt5.QtWidgets:提供了创建图形用户界面 (GUI) 的基本控件和窗口类
- PyQt5.QtGui:提供了图形和图像处理功能。
- PyQt5.QtCore:提供了核心的非 GUI 功能,包括基本的数据类型和事件处理。
2.定义自定义矩形图形项类 CustomRectItem:
-
init 方法:初始化矩形项的颜色和初始位置,并设置移动速度。
-
advance 方法:更新矩形项的位置,检测边界和碰撞,并在碰撞时改变颜色。
3.定义自定义椭圆图形项类 CustomEllipseItem:
- 类似于 CustomRectItem,但初始移动方向和碰撞时的颜色不同。
4.定义视图类 GraphicsView:
-
init 方法:初始化视图,启用抗锯齿渲染并设置拖动模式。
-
wheelEvent 方法:实现使用鼠标滚轮进行缩放。
5.主程序入口:
- 创建 QApplication 实例。
- 创建 QGraphicsScene 场景,并设置场景的边界。
- 创建 CustomRectItem 和 CustomEllipseItem,并将它们添加到场景中。
- 创建 GraphicsView 实例,并将场景设置到视图中。
- 使用 QTimer 来定时更新图形项的位置,并检测碰撞。
- 启动应用程序的事件循环。
运行效果:
- 一个包含两个图形项(矩形和椭圆)的场景。
- 矩形和椭圆在场景中移动,碰到边界时会反向移动。
- 矩形和椭圆碰撞时会改变颜色。
- 可以使用鼠标滚轮缩放视图。
完整代码
import sys
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsRectItem, QGraphicsEllipseItem
from PyQt5.QtGui import QPainter, QBrush, QColor, QPen
from PyQt5.QtCore import QRectF, QTimer
class CustomRectItem(QGraphicsRectItem):
def __init__(self, color, rect):
super().__init__(rect)
self.setBrush(QBrush(color))
self.setPen(QPen(QColor(0, 0, 0)))
self.dx = 2 # 水平方向移动速度
self.dy = 2 # 垂直方向移动速度
def advance(self, phase):
if phase == 0:
return
# 移动图形项
new_x = self.x() + self.dx
new_y = self.y() + self.dy
# 边界检测
if new_x < -300 or new_x + self.rect().width() > 300:
self.dx = -self.dx # 反向移动
if new_y < -300 or new_y + self.rect().height() > 300:
self.dy = -self.dy # 反向移动
self.moveBy(self.dx, self.dy)
# 检测碰撞并改变颜色
if self.collidingItems():
self.setBrush(QBrush(QColor(255, 0, 0, 100))) # 半透明红色
else:
self.setBrush(QBrush(QColor(0, 255, 0, 100))) # 半透明绿色
class CustomEllipseItem(QGraphicsEllipseItem):
def __init__(self, color, rect):
super().__init__(rect)
self.setBrush(QBrush(color))
self.setPen(QPen(QColor(0, 0, 0)))
self.dx = -2 # 水平方向移动速度
self.dy = -2 # 垂直方向移动速度
def advance(self, phase):
if phase == 0:
return
# 移动图形项
new_x = self.x() + self.dx
new_y = self.y() + self.dy
# 边界检测
if new_x < -300 or new_x + self.rect().width() > 300:
self.dx = -self.dx # 反向移动
if new_y < -300 or new_y + self.rect().height() > 300:
self.dy = -self.dy # 反向移动
self.moveBy(self.dx, self.dy)
# 检测碰撞并改变颜色
if self.collidingItems():
self.setBrush(QBrush(QColor(0, 0, 255, 100))) # 半透明蓝色
else:
self.setBrush(QBrush(QColor(255, 255, 0, 100))) # 半透明黄色
class GraphicsView(QGraphicsView):
def __init__(self, scene):
super().__init__(scene)
self.setRenderHint(QPainter.Antialiasing)
self.setDragMode(QGraphicsView.ScrollHandDrag)
def wheelEvent(self, event):
# 使用鼠标滚轮进行缩放
zoomInFactor = 1.15
zoomOutFactor = 1 / zoomInFactor
if event.angleDelta().y() > 0:
zoomFactor = zoomInFactor
else:
zoomFactor = zoomOutFactor
self.scale(zoomFactor, zoomFactor)
if __name__ == '__main__':
app = QApplication(sys.argv)
# 创建场景
scene = QGraphicsScene()
scene.setSceneRect(-300, -300, 600, 600)
# 创建两个自定义矩形图形项并添加到场景
rect_item = CustomRectItem(QColor(0, 255, 0, 100), QRectF(0, 0, 100, 100))
rect_item.setPos(-150, -150)
scene.addItem(rect_item)
# 创建两个自定义椭圆图形项并添加到场景
ellipse_item = CustomEllipseItem(QColor(255, 255, 0, 100), QRectF(0, 0, 100, 100))
ellipse_item.setPos(50, 50)
scene.addItem(ellipse_item)
# 创建视图并设置场景
view = GraphicsView(scene)
view.show()
# 使用定时器来更新图形项的位置和检测碰撞
timer = QTimer()
timer.timeout.connect(lambda: scene.advance())
timer.start(100)
sys.exit(app.exec_())