一键停止打开多个窗口

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

在我的代码中有一个打开新窗口的按钮,并且一直在尝试使按钮打开一个名为

newest_release_window
的新窗口,并记住两件事:

  • 如果
    newest_release_window
    未打开,请打开窗口。
  • 如果
    newest_release_window
    打开,将焦点设置在该窗口上,但不要打开新窗口。

不幸的是,它变得太复杂了,我不知道该怎么做。问题是我无法让代码检测

newest_release_window
是否打开,并据此更改变量。

welcome_window = Tk()
welcome_window.title("Games R Us")
welcome_window.geometry("360x350")
welcome_window.configure(bg = "gold")
currentDisplay = 10

newest_release_windowtracker = 0

gui_font_5 = ("Helvetica", 5, "bold")
gui_font_10 = ("Helvetica", 10, "bold")
gui_font_15 = ("Helvetica", 15, "bold")
gui_font_20 = ("Helvetica", 20, "bold")
space_between = (5)
button_variable = IntVar()

def newwindow_newest_release():
    global newest_release_windowtracker
    newest_release_window = Tk()
    newest_release_window.title("Games R Us")

    newest_release_window.geometry("360x350")
    newest_release_window.configure(bg = "greenyellow")
    currentDisplay = 10
    
    display = Label(newest_release_window, text="Humm, see a new window !", 
    bg ="limegreen")
    display.pack()
    
    newest_release_window.withdraw()
    
    if newest_release_windowtracker == 0:
        newest_release_window.deiconify()
        newest_release_windowtracker = 1
    elif newest_release_windowtracker == 1:
        newest_release_window.focus_set()
    elif newest_release_window.winfo_exists == 0:
        newest_release_window = Tk()

ww_newest_release = Button(welcome_window,
            text = "Newest Release", bg = "goldenrod", font = "Helvetica 10", 
            width = 12, command = newwindow_newest_release)

这不是完整的代码,我只是抓住了最重要的部分来为可能出现的问题提供背景信息。

python python-3.x tkinter tk-toolkit
3个回答
0
投票

您可以设置一个布尔值来定义窗口是否打开,如果打开,则在

lift()
tkinter.Tk
的实例上调用
tkinter.Toplevel
方法。

检查窗口是否存在: 如果 newest_release 窗口上方有

root
类,您可以检查
hasattr(base_class, 'newest_release')
。如果没有,那么您可以像这样
global newest_release
将窗口设置为全局变量,以便您可以在函数外部访问它。然后你可以创建这样的代码:

if 'newest_release' in globals():
    newest_release.lift()

if hasattr(base_class, 'newest_release'):
    newest_release.lift()

0
投票

我这样做的方法是使用一个变量来存储 Toplevel 实例。我首先将该变量初始化为 None,所以我只能设置它一次(通过测试变量是否为 None)

当 Toplevel 被销毁时(通过绑定

WM_DELETE_WINDOW
协议),该变量将重置回 None。

我还注意到,在您的代码中,您正在实例化一个新的

Tk()
对象。
Tk()
对象只能实例化一次,并且是程序的根。要打开新窗口,您应该使用
Toplevel
对象。

现在举个例子:

import tkinter as tk


class OptionsWindow(tk.Frame):
    def __init__(self, master=None, **kwargs):
        super().__init__(master, **kwargs)
        pass


class MainWindow(tk.Frame):
    def __init__(self, master=None, **kwargs):
        super().__init__(master, **kwargs)
        self.options_toplevel = None
        tk.Button(self, text='open toplevel', command=self._open_toplevel).pack()

    def _open_toplevel(self, *args):
        if self.options_toplevel is None:
            self.options_toplevel = tk.Toplevel(self.master)
            self.options_toplevel.protocol('WM_DELETE_WINDOW', self.on_tl_close)
            gui = OptionsWindow(self.options_toplevel, width=300, height=300)
            gui.pack()

    def on_tl_close(self, *args):
        self.options_toplevel.destroy()
        self.options_toplevel = None


root = tk.Tk()
gui = MainWindow(root)
gui.pack()
root.mainloop()

0
投票

您想要做的是生成一个

TopLevel
窗口。

为了防止生成顶层的多个实例,请存储其引用并在单击按钮时对其进行检查。

    ...
    
    self.options_toplevel = None

    def _open_toplevel(self):
        if self.options_toplevel is None:
            self.options_toplevel = OptionsWindow(self.master)

如果您想通过单击操作将用户返回到顶层,您可以

lift()
将窗口返回到顶部,然后调用
focus_set()
将键盘和鼠标事件再次定向到顶层窗口。

        else:
            self.options_toplevel.lift()
            self.options_toplevel.focus_set()

还值得一提的是,您可以将事件绑定到窗口销毁协议。这允许您在窗口被销毁时定义其他操作,因此如果您的用例出于某种原因需要这样做,您可以使用它来实现类似的效果。

    ...    

    self.protocol("WM_DELETE_WINDOW", self.on_close)
    
    def on_close(self):
        # Any cleanup you need to do.
        self.grab_release()
        self.destroy()

现在我们可以将所有这些放在一个可行的示例中。

import tkinter as tk


class OptionsWindow(tk.Toplevel):
    def __init__(self, root=None, **kwargs):
        super().__init__(root, **kwargs)
        self.title("Options Window")
        self.geometry("300x300")

        # Bind action to the tk close protocol
        self.protocol("WM_DELETE_WINDOW", self.on_close)

        tk.Label(self, text="This is the options window").pack(pady=20)
        tk.Button(self, text="Close", command=self.destroy).pack(pady=10)

        self.focus_set()  # Move cursor & keyboard focus to the toplevel window

    def on_close(self):
        # Any cleanup you need to do.
        self.grab_release()
        self.destroy()


class MainWindow(tk.Frame):
    def __init__(self, root=None, **kwargs):
        super().__init__(root, **kwargs)

        self.options_toplevel = None

        tk.Button(self, text='Open Options', command=self._open_toplevel).pack()
        tk.Button(self, text='Open Options', command=self.do_stuff).pack()

    def _open_toplevel(self, *args):
        if self.options_toplevel is None or not tk.Toplevel.winfo_exists(self.options_toplevel):
            self.options_toplevel = OptionsWindow(self.master)
        else:
            self.options_toplevel.lift()
            self.options_toplevel.focus_set()

    def on_toplevel_close(self, *args):
        if self.options_toplevel:
            self.options_toplevel = None

    def do_stuff(self):
        print("Doing stuff!!1")


root = tk.Tk()
root.title("Main Window")
gui = MainWindow(root)
gui.pack(pady=20, padx=20)
root.mainloop()

模态示例:

如果目标是设计更多模式,用户必须先响应

TopLevel
,然后才能与基本应用程序交互,那么您可以使用
grab_set()
并设置 '-topmost' 属性来实现这一目标。

        ...

        self.attributes("-topmost", True)
        self.focus_set()
        self.grab_set()

下面的示例足以防止生成更多窗口,但您可能应该包含主要示例中编写的保护措施。

import tkinter as tk


class OptionsWindow(tk.Toplevel):
    def __init__(self, root=None, **kwargs):
        super().__init__(root, **kwargs)
        self.attributes("-topmost", True)

        tk.Label(self, text="This is the options window").pack(pady=20)
        tk.Button(self, text="Close", command=self.destroy).pack(pady=10)

        self.focus_set()  # Move focus to the toplevel window
        self.grab_set()   # Restrict user interaction to the top level until its closed

class MainWindow(tk.Frame):
    def __init__(self, master=None, **kwargs):
        super().__init__(master, **kwargs)

        tk.Button(self, text='Open Options', command=self._open_toplevel).pack()

    def _open_toplevel(self):
        OptionsWindow(self.master)

root = tk.Tk()
root.title("Main Window")
gui = MainWindow(root)
gui.pack(pady=20, padx=20)
root.mainloop()

如果您想了解更多信息,我建议您查看 Tk: Toplevel 的文档。

© www.soinside.com 2019 - 2024. All rights reserved.