如何在运行iconify后使tkinter窗口最小化后不可访问?
我正在尝试同时打开一个tkinter窗口和一个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的循环更新,导致两个窗口都崩溃。我之所以这么想,是因为print("init"*50)
在正常情况下和有问题的情况下都没有运行,只有在正常工作时,tkinter窗口被关闭时才会运行。
所以,我成功的地方在于能够同时打开这两种窗口,而不成功的地方在于这种行为无法稳定发生。我非常感谢任何帮助,感谢你花时间阅读这个问题。
编辑 2:
我把问题缩小到运行tkinter窗口的update()
或mainloop()
方法,尽管我仍然不知道为什么这些方法对我不起作用。当运行这些方法时,整个程序会崩溃,但没有错误代码。任何在这些方法之前的代码都能正常运行,但之后的代码就无法执行。我能想到这些方法不工作的唯一原因是,可能有些需要定义的东西没有定义,但:
- 没有错误代码提示这个问题,
- 这些方法似乎只需要窗口被定义,而窗口确实是定义好的。
编辑 3:
在尝试评论中提到的方法,使用iconify()
和deiconify()
后,我发现这个方法基本上可以正常工作,只是它可以在任何时候打开。如果有办法在tkinter窗口被最小化、隐藏或“图标化”时不允许打开它,可能会解决我的问题。
1 个回答
感谢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()