如何将Pygame的窗口嵌入PyQt5窗口中(源码

Chapter 1 前言

事情是这样的:我打算开发一个将手柄按键映射到键盘的程序,我想完善这个程序到一个足够完善的程序,因此这个程序需要一定的图形界面。但问题出现了,我的手柄界面已经通过Pygame的精灵绘制出来了,但同时,我又想用PyQt5绘制工具栏、添加按键等等,不言而喻,使用PyQt5绘制这些东西要快得多。

这个时候问题就出现了:如何将Pygame的窗口嵌入PyQt的窗口中?

Chapter 2.1 实现思路

Pygame和PyQt作为两个不同的模块,不说紧密联系,也至少是毫无关系了。但PyQt中有可以插入图片的Label——Qlabel,如果我们能够将Pygame的窗口(后称Surface)转化为一个图片,并将这个图片贴到Qlabel中即可。

Chapter2.2 具体实现

 PyQt提供了surface2pixmap()函数来转化图片: pixmap = self.surface2pixmap(pygame_surface)。因此我们只需要继承来自Designer的窗口类,并在这个子类中加入一个Qlabel,而后将转化后的pixmap通过self.image_label.setPixmap(pixmap)贴到Qlabel中就好了。

如上图,我在Pygame的Surface中绘制了一个圆,并将这个圆贴到了PyQt的窗口中。如果你开启了Qlabel的图片自适应大小self.image_label.setScaledContents(True) ,那么Surface的内容就会跟随Qlabel的大小,如果二者长宽比不一致,也会导致Surface被拉伸,使用时自己注意就好了。

另外,还要多一嘴:surface可以从脏矩形哪儿获取绘制内容,如果你的代码管理的好的话,应该说这种将Pygame嵌入PyQt的方法是挺高效的。

Chapter 3 源代码(需要修改,继承你自己的UI类即可)

import pygame
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QHBoxLayout, QWidget
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QPixmap

# Import your generated UI file
from MAINWINDOW import Ui_MainWindow

class MyWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("Pygame and PyQt5 Integration")
        self.setup_pygame()

        # 创建一个QLabel用于显示图片
        self.image_label = QLabel(self)
        self.image_label.setGeometry(QtCore.QRect(100, 100, 300, 400))  # 设置 QLabel 的位置和大小
        self.image_label.setObjectName("image_label")

        # 创建 Pygame Surface(这里简单地创建一个红色的 Surface)
        pygame_surface = pygame.Surface((100, 100))
        pygame_surface.fill((0, 0, 0))  # 黑色
        pygame.draw.circle(pygame_surface, (255, 0, 0), (50, 50), 50)

        # 加载图片
        # image_path = 'LAB_Wreck_Eclipse.png'  # 替换为你的图片路径
        pixmap = self.surface2pixmap(pygame_surface)
        self.image_label.setPixmap(pixmap)
        self.image_label.setScaledContents(True)  # 图片自适应 QLabel 大小

        timer = QTimer(self)
        timer.timeout.connect(self.update)
        timer.start(int(1000 / 60))
        self.show()

    def setup_pygame(self):
        # Add your Pygame integration code here
        pass

    def update(self):
        # Add your update logic here
        pass

    def surface2pixmap(self, pygame_surface):
        # 将 Pygame Surface 转换为 QImage
        image = QImage(pygame.image.tostring(pygame_surface, 'RGB'), pygame_surface.get_width(),
                       pygame_surface.get_height(), QImage.Format_RGB888)
        # 将 QImage 转换为 QPixmap
        return QPixmap(image)

if __name__ == "__main__":
    pygame.init()
    app = QApplication(sys.argv)
    window = MyWindow()
    sys.exit(app.exec_())