我试图同时打开一个 tkinter 窗口和一个 pygame 窗口,我到处搜索并提出了我已经修剪过的代码,以便它是一个具有尽可能少的代码的最小可行产品,因为粘贴了所有这里的代码将包含许多不同的封装方法和类,这显示了我的代码的主要思想。我想在单击主 pygame 屏幕上的 pygame 按钮时打开一个 tkinter 窗口,并且我已经成功设置了一个类,该类允许我通过单击所述 pygame 按钮来创建窗口。有时这不起作用,但当我不经常移动鼠标时,它就会起作用。这是我对正在发生的事情的最好解释,因为我不知道还有什么可能导致这个问题。如果问题是它从来没有起作用,我就会放弃这种方法,但当鼠标移动缓慢且机械化时,它确实有效。我对所有建议持开放态度,因为我很困惑。
import pygame as pg
import tkinter as tk
import os
from tkinter import ttk
# imports
# pg setup
pg.init()
screen = pg.display.set_mode((400,400))
screen.fill("black", pg.Rect((0,0), (400,400)))
# the encapsulated tkinter class
class FriendDialogue(tk.Tk):
def __init__(self, title):
self.root = super().__init__()
self._title = title
self.geometry("450x150")
self.title(self._title)
friend_dialogue.protocol("WM_DELETE_WINDOW", self.del_friend_window) # set
# the function to override the [x] button on tkinter window so that
# the window doesn't open multiple times
self.iconify()
def del_friend_window():
self.destroy()
self.root = None
friend_dialogue = FriendDialogue("Phone a friend") # create new tkinter window
# to make it so the button (screen) only works once
notRun = True
# main loop
while True:
for event in pg.event.get(): # event loop
if event.type == pg.QUIT: # [x] button on pg window
exit()
if event.type == pg.MOUSEBUTTONDOWN and notRun: # if click on screen
notRun = False # to run once
friend_dialogue.deiconify()
pg.display.update() # update pygame window
if friend_dialogue.root: # if not clicked yet, this won't run
friend_dialogue.update()
编辑: 目前使用上述代码,窗口将始终打开,但有时它会立即关闭,而其他时候它会保持打开状态并可操作。当发生这种情况时,pygame 窗口停止运行并且 tkinter 窗口可以操作,这是我想要的行为。 问题是,其他时候,使用相同的代码,tkinter 窗口将打开,然后,在两个窗口都没有响应几秒钟后,两个窗口都会崩溃。我相信有时主循环会超越主线程,而其他时候主循环无法启动,扰乱 pygame while 循环更新,使两个窗口崩溃。 我认为这是因为
print("init"*50)
永远不会在预期和错误行为中运行,除非该行为按预期工作,然后使用 [x] 按钮关闭 tkinter 窗口。
所以,我成功的地方在于允许这两种类型的窗口同时打开,而我不成功的地方在于允许这种行为持续发生。我感谢任何帮助,感谢您花时间阅读这个问题。
编辑2: 我已将问题范围缩小到运行 tkinter 窗口的
update()
或 mainloop()
方法,尽管我仍然不知道为什么这些方法对我不起作用。当这些方法运行时,整个程序崩溃,没有错误代码。这些方法运行之前的任何代码都可以正常工作,但之后的任何代码都不会运行。我能想到这些方法不起作用的唯一原因是,如果需要为这些方法定义的内容不是:
编辑3: 在尝试了评论中涉及使用
iconify()
和deiconify()
的方法后,我发现它工作得很好,除了可以随时打开之外。如果无论如何都不允许 tkinter 窗口在图标、撤回或“图标化”时打开,它可能会解决我的问题。
感谢acw1668的解决方案: “我建议创建一个 FriendDialogue 实例作为根窗口并使其最初隐藏。然后使用 .after() 为 pygame 创建循环。当鼠标在 pygame 窗口上单击时,显示(去图标)根窗口。单击 tkinter 根窗口标题栏中的关闭按钮时,隐藏(撤回)根窗口。”
我不需要实现
.after()
,所以对于将来的其他人来说,这就是我实现它的方式,同时打开 pygame 和 tkinter 窗口,然后能够根据命令关闭和打开。
import pygame as pg
import tkinter as tk
import os
from tkinter import ttk
pg.init()
screen = pg.display.set_mode((400,400))
screen.fill("black", pg.Rect((0,0), (400,400)))
class FriendDialogue(tk.Tk):
def __init__(self, title):
self.root = super().__init__()
self.geometry("450x150")
self.title(title)
self.withdraw()
friend_dialogue = FriendDialogue("Phone a Friend")
opened = False
while True:
for event in pg.event.get():
if event.type == pg.QUIT:
exit()
if event.type == pg.MOUSEBUTTONDOWN and not opened:
opened = True
friend_dialogue.deiconify()
if opened:
friend_dialogue.update()
pg.display.update()