大爽pyqt5笔记&教程 五 运动游戏基础 QGraphicsView 和 QGraphicsScene

这篇博客介绍了如何利用PyQt5的QGraphicsView和QGraphicsScene组件来创建一个图像移动的基础实现。通过创建QGraphicsPixmapItem对象并响应键盘事件,实现了图像在窗口中按WASD键上下左右移动的功能,提供了一种适用于游戏开发的图像运动基础框架。

作者自我介绍:大爽歌, b站小UP主
python1对1辅导老师
时常直播编程,直播时免费回答简单问题。

14 位图移动逻辑基础实现

运动游戏的核心基础是,通过按键能够实现图片的运动(比如上下左右移动)。

虽然使用QLabel也能够展示图片,并且通过setGeometory也能设定位置,但是这样处理运动并不友好。

更推荐使用QGraphicsViewQGraphicsScene

QGraphicsView和QGraphicsScene

这两个要一般要一起配合使用。
其中QGraphicsView作为控件,占据面板一片区域。
QGraphicsScene则作为场景,用于添加位图项目。

基础代码如下

from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import *

import sys


class MyWindow(QWidget):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.resize(300, 200)
        self.init_gui()

        self.show()

    def init_gui(self):
        box = QVBoxLayout()
        label = QLabel("Basic Move", self)

        self.view = QGraphicsView()
        self.scene = QGraphicsScene()
        self.view.setScene(self.scene)

        box.addWidget(label)
        box.addWidget(self.view)

        self.setLayout(box)

效果如图

注意这几行

self.view = QGraphicsView()
self.scene = QGraphicsScene()
self.view.setScene(self.scene)

box.addWidget(self.view)
  • QGraphicsView使用QGraphicsScene作为场景
  • QGraphicsView可以看作控件添加到上级的layout中。

动画区域要添加运动的图片,则是QGraphicsScene来添加。
比如添加一个图片,且实现基础的移动功能。

此时里面的位图要使用QGraphicsPixmapItem控件来展示。

添加图片与运动

添加图片和响应键盘操作运动。
可以在MyWindow类添加如下方法

def set_view(self):
    self.item = QGraphicsPixmapItem()  # 新建QGraphicsPixmapItem对象用于显示图片
    self.item.setPixmap(QPixmap("my_logo.png"))  # 设置位图
    self.item.setPos(100, 100)  # 设置图片位置
    self.scene.addItem(self.item)  # 添加图片到scene中

    self.view.setFixedSize(300, 300)  # 设置view为固定尺寸 300x300
    self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关闭水平方向滚动条
    self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)  # 关闭竖直方向滚动条

def keyPressEvent(self, event):
    if event.key() == Qt.Key_W:  # 按W键上移
        self.item.setPos(self.item.x(), self.item.y()-10)
    elif event.key() == Qt.Key_S:  # 按S键上移
        self.item.setPos(self.item.x(), self.item.y()+10)
    elif event.key() == Qt.Key_A:  # 按A键左移
        self.item.setPos(self.item.x()-10, self.item.y())
    elif event.key() == Qt.Key_D:  # 按D键右移
        self.item.setPos(self.item.x()+10, self.item.y())

且在init_gui方法中(末尾处)添加一句代码

self.set_view()

此时效果如图

此时按方向键就可以移动图片了。

总代码
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import *

import sys


class MyWindow(QWidget):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.resize(300, 200)
        self.init_gui()

        self.show()

    def init_gui(self):
        box = QVBoxLayout()
        label = QLabel("Label Text", self)

        self.view = QGraphicsView()
        self.scene = QGraphicsScene()
        self.view.setScene(self.scene)

        box.addWidget(label)
        box.addWidget(self.view)

        self.set_view()
        self.setLayout(box)

    def set_view(self):
        self.item = QGraphicsPixmapItem()  # 新建QGraphicsPixmapItem对象用于显示图片
        self.item.setPixmap(QPixmap("my_logo.png"))  # 设置位图
        self.item.setPos(100, 100)  # 设置图片位置
        self.scene.addItem(self.item)  # 添加图片到scene中

        self.view.setFixedSize(300, 300)  # 设置view为固定尺寸 300x300
        self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 关闭水平方向滚动条
        self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)  # 关闭竖直方向滚动条

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_W:  # 按W键上移
            self.item.setPos(self.item.x(), self.item.y()-10)
        elif event.key() == Qt.Key_S:  # 按S键上移
            self.item.setPos(self.item.x(), self.item.y()+10)
        elif event.key() == Qt.Key_A:  # 按A键左移
            self.item.setPos(self.item.x()-10, self.item.y())
        elif event.key() == Qt.Key_D:  # 按D键右移
            self.item.setPos(self.item.x()+10, self.item.y())


app = QApplication(sys.argv)
win = MyWindow()
sys.exit(app.exec_())
<think>好的,用户想学习PyQt6中QGraphicsViewQGraphicsScene的用法,需要教程示例代码。首先,我需要整理这两个组件的基本结构层级关系。根据引用内容,QGraphicsView是视图,包含QGraphicsScene场景,而场景中又包含各种图形项,比如矩形、椭圆、文本等[^1]。 接下来,用户可能需要基础的示例代码来理解如何创建场景视图。查看引用中的例子,比如引用3中的代码,可以展示如何初始化场景、视图,并添加简单的图形项。但要注意用户使用的是PyQt6,可能需要调整导入语句,比如将PySide6改为PyQt6的模块。 然后,需要介绍如何添加不同类型的图形项,比如椭圆、文本,以及自定义项。这部分需要确保使用正确的类方法,比如addEllipse、addText等。同时,自定义项可能需要继承QGraphicsItem并重写paintboundingRect方法,但根据引用2中的建议,更推荐使用现有的图形项,除非有必要自定义。 用户可能还关心如何实现交互功能,比如鼠标事件。引用4提到了如何处理鼠标点击事件,可以通过子类化QGraphicsView并重写mousePressEvent来实现。这部分需要详细说明,并提供示例代码,确保用户能够实现交互效果。 另外,动画刷新机制也是常见需求。引用4中的QPixmap更新可能涉及定时器场景更新方法,比如使用QTimer定时调用update,然后重写paint事件。需要给出一个简单的动画示例,比如移动矩形,展示如何通过定时器修改位置并刷新视图。 最后,整理常见问题使用技巧,比如坐标系的理解、性能优化(量图形项的处理)、事件传递机制等,帮助用户避免常见陷阱。确保引用相关文献,如引用1的结构引用3的示例代码,增强回答的可信度。 检查所有代码是否符合PyQt6的语法,比如导入语句是否正确,方法名是否有变化。同时,确保所有数学公式变量使用$...$格式,独立公式用$$...$$,但当前问题不涉及数学公式,可能不需要处理这部分。 总结回答的结构,先介绍组件层级,再分步讲解基础使用、图形项添加、交互、动画,最后注意事项。确保每个部分都有代码示例引用支持,语言简洁明了,符合中文表达习惯。</think>### PyQt6 QGraphicsView QGraphicsScene 使用教程 #### 一、组件层级与基本概念 PyQt6 中的图形视图框架由三部分组成: - **QGraphicsView**(视图):负责显示场景内容,支持缩放、旋转等交互操作[^1]。 - **QGraphicsScene**(场景):管理图形项的容器,处理事件传播坐标变换[^2]。 - **QGraphicsItem**(图形项):如矩形、椭圆、文本等,支持自定义绘制[^1]。 #### 二、基础使用示例 以下代码演示如何创建场景视图,并添加一个矩形: ```python from PyQt6.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsRectItem from PyQt6.QtCore import Qt app = QApplication([]) # 创建场景视图 scene = QGraphicsScene() view = QGraphicsView(scene) view.setWindowTitle("基础示例") # 添加矩形项 rect = scene.addRect(0, 0, 100, 50) # (x, y, width, height) rect.setBrush(Qt.GlobalColor.blue) # 设置填充颜色 view.show() app.exec() ``` 此代码会显示一个蓝色矩形,视图默认小为 640x480[^3]。 #### 三、添加不同类型图形项 1. **椭圆与文本** ```python # 添加椭圆 ellipse = scene.addEllipse(50, 50, 80, 60, brush=Qt.GlobalColor.red) # 添加文本 text = scene.addText("Hello PyQt6") text.setPos(100, 100) # 设置文本位置 ``` 2. **自定义图形项** ```python class CustomItem(QGraphicsRectItem): def paint(self, painter, option, widget=None): painter.drawRect(self.rect()) painter.drawText(20, 20, "自定义项") custom_item = CustomItem(0, 0, 120, 80) scene.addItem(custom_item) ``` #### 四、交互与事件处理 实现鼠标点击移动矩形: ```python class InteractiveView(QGraphicsView): def mousePressEvent(self, event): item = self.scene().itemAt(self.mapToScene(event.pos()), self.transform()) if isinstance(item, QGraphicsRectItem): item.setPos(100, 100) # 点击后移动矩形位置 super().mousePressEvent(event) # 使用时替换视图类 view = InteractiveView(scene) ``` 此代码重写了视图的鼠标事件,点击矩形会改变其位置[^4]。 #### 、动画与刷新 通过定时器实现简单动画: ```python from PyQt6.QtCore import QTimer rect = scene.addRect(0, 0, 30, 30) timer = QTimer() timer.timeout.connect(lambda: rect.setPos(rect.x() + 1, rect.y())) timer.start(50) # 每50ms移动1像素 ``` #### 六、注意事项 1. **坐标系**:场景坐标系以中心为原点,视图坐标系以左上角为原点 2. **性能优化**:超过10,000个图形项时建议使用`QGraphicsWidget`或分页加载 3. **事件传递**:优先级顺序为:图形项 > 场景 > 视图
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值