我将pygame窗口嵌入到Tkinter中,如何操作pygame窗口?

时间:2019-04-19 00:50:52

标签: python tkinter pygame embed

所以我正在pygame中制作游戏,我也想使用tkinter。我将pygame窗口嵌入到tkinter窗口中,但是我似乎对此无能为力。

对于上下文,这是完整的代码:

import Tkinter as tk
import os
import platform
import pygame

class window(object):
    def __init__(self):
        self.root = tk.Tk()  # Main window
        self.root.title("SquareScape")
        self.root.iconbitmap(r'C:\Users\17_es\PycharmProjects\square_puzzle\images\icon.ico')
        self.root.configure(background='#9b9b9b')

        # Large Frame
        self.win_frame = tk.Frame(self.root, width=670, height=520, highlightbackground='#595959', highlightthickness=2)

        # menu (left side)
        self.menu = tk.Frame(self.win_frame, width=150, height=516, highlightbackground='#595959', highlightthickness=2)
        self.menu_label = tk.Label(self.menu, text="Settings", bg='#8a8a8a', font=("Courier", "16", "bold roman"))
        self.mute = tk.Button(self.menu, text="XXXX", font="Courier", bg='#bcbcbc', activebackground='#cdcdcd')

        # pygame
        self.pygame_frame = tk.Frame(self.win_frame, width=514, height=514, highlightbackground='#595959', highlightthickness=2)
        self.embed = tk.Frame(self.pygame_frame, width=512, height=512,)

        # Packing
        self.win_frame.pack(expand=True)
        self.win_frame.pack_propagate(0)

        self.menu.pack(side="left")
        self.menu.pack_propagate(0)
        self.menu_label.pack(ipadx=60, ipady=2)
        self.mute.pack(ipadx=40, ipady=2, pady=5)

        self.pygame_frame.pack(side="left")
        self.embed.pack()

        #This embeds the pygame window
        os.environ['SDL_WINDOWID'] = str(self.embed.winfo_id())
        if platform.system == "Windows":
            os.environ['SDL_VIDEODRIVER'] = 'windib'

        #Start pygame
        pygame.init()
        self.win = pygame.display.set_mode((512, 512))
        self.win.fill(pygame.Color(255, 255, 255))
        pygame.display.init()

        self.root.mainloop()

screen = window()

#Here is sample code that I want to run
pygame.draw.rect(screen.win, (0, 0, 255), (200, 200, 100, 100))

当我使用pygame.draw.rect(screen.win, (0, 0, 255), (200, 200, 100, 100))时,什么也没发生。在类内部使用pygame是可行的,但是在我更复杂的游戏中,对所有变量都使用self.variable似乎没有必要。

如何在窗口类之外的pygame窗口中运行代码?

1 个答案:

答案 0 :(得分:0)

因此-除了明显缺少对pygame.display.flip的呼叫-我想这是您对pygame.display.init的呼叫的意图(pygame.init已经呼叫了那个)-我发现的是tkinter需要在打包的框架完全可供Pygame使用之前初始化其窗口和小部件。

为此,我在调用self.root.update_idletasks()之前添加了对pygame.init的调用-并为我的平台显式设置了视频驱动程序(您已经在Windows中进行了此操作),使一切正常。 / p>

无论如何,无论如何,您都没有在代码中显示是否要调用Pygamedrawing函数-照原样,一切都可能正确,但是screen.window()之后的代码永远不会运行(或更确切地说,仅在程序出口运行)-因为您在应用程序类的__init__方法内调用了tkinter.mainloop。

将调用移到mainloop之外是一个好习惯,因此您也可以初始化其他对象和资源-实际上您确实拥有__init__对象来进行操作上。通过在screen中进行该调用,就好像您的整个程序都在“初始化中”运行一样。

简而言之:

  • 在初始化pygame之前先呼叫__init__
  • 在使用Pygame绘制任何内容后,请记住致电tkinter.update_iddletasks()
  • 安排代码,以便实际执行绘图调用,并且在调用进入tkinter循环后不会阻塞
  • 您应该认真考虑使用Python 3.7或更高版本-(唯一的“ python 2”代码中有pygame.display.flip,在Python 3中变成了import Tkinter)。 Python 2排在最后,确实,并且没有像pygame这样的项目的更新。 。

也就是说,这是您的代码,经过修改后可以在Linux + Python 3上运行(仍应在Windows上运行),并使用嵌入式pygame框架实际执行一些操作。

import tkinter