如何使 tkinter 在 iconify 运行后最小化时不可访问?

问题描述 投票:0回答:1

我试图同时打开一个 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()
方法,尽管我仍然不知道为什么这些方法对我不起作用。当这些方法运行时,整个程序崩溃,没有错误代码。这些方法运行之前的任何代码都可以正常工作,但之后的任何代码都不会运行。我能想到这些方法不起作用的唯一原因是,如果需要为这些方法定义的内容不是:

  1. 没有错误代码表明出现此问题,并且
  2. 这些方法大概只需要定义窗口。

编辑3: 在尝试了评论中涉及使用

iconify()
deiconify()
的方法后,我发现它工作得很好,除了可以随时打开之外。如果无论如何都不允许 tkinter 窗口在图标、撤回或“图标化”时打开,它可能会解决我的问题。

python tkinter pygame python-multithreading
1个回答
0
投票

感谢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()
© www.soinside.com 2019 - 2024. All rights reserved.