Tkinter: open a new window from another window only once

With the following code you will be able to open a new window from the root window. We’ve done it yet into a post of some days ago, but in that code you could open the same window as many times as you wanted. What if you do want to prevent the chance for the user to open it more times, but just create it once? I thought to this solutions that uses the state() method of Tk(), to check if the window is open. If it is, it will return you ‘normal’ as state. I put the code into a try except:

if the window does not exist => the error will raise an exception (NameError)

if the window state is normal => it focus on the window, not creating another window

Code with Class

In this first example we are going to use a class Win2 to build a very basic window, that is called by the function new_window triggered by the click of the button.

import tkinter as tk


def new_window(Win_class):
    global win2
    try:
        if win2.state() == "normal": win2.focus()
    except NameError as e:
        print(e)
        win2 = tk.Toplevel(win)
        Win_class(win2)

class Win2:
    def __init__(self, root):
        self.root = root
        self.root.geometry("300x300+500+200")
        self.root["bg"] = "navy"


win = tk.Tk()
win.geometry("200x200+200+100")
button = tk.Button(win, text="Open new Window")
button['command'] = lambda: new_window(Win2)
button.pack()
text = tk.Text(win, bg='cyan')
text.pack()
win.mainloop()

A different version without Class, with a function

If you need something very simple and no more than one type of windows, you can also use this very simple code:

import tkinter as tk


def new_window1():
    " new window"
    try:
        if win1.state() == "normal": win1.focus()
    except NameError as e:
        print(e)
        win1 = tk.Toplevel()
        win1.geometry("300x300+500+200")
        win1["bg"] = "navy"
        lb = tk.Label(win1, text="Hello")
        lb.pack()


win = tk.Tk()
win.geometry("200x200+200+100")
button = tk.Button(win, text="Open new Window")
button['command'] = new_window1
button.pack()
win.mainloop()

Video about making one window from the another only once

Tkinter test for students

Tkinter articles

Other suggested post about tkinter:

Open a new window once with he Azure dark theme





import tkinter as tk
from tkinter import ttk


class App(ttk.Frame):
    def __init__(self, parent):
        ttk.Frame.__init__(self)
        self.win2_status = 0 # to open the new window once
        self.setup_frames()
        self.setup_button()

    def setup_frames(self):
        # frame for button --------------- frame 0 / button
        self.button_frame0 = ttk.LabelFrame(self, text="Azure dark Theme App", padding=(20, 10))
        self.button_frame0.grid(
            row=0, column=0, padx=(20, 10), pady=(20, 10), sticky="nsew")

    def setup_button(self):
        self.accentbutton = ttk.Button(
        self.button_frame0,
        text="CLick to open new window", 
        style="Accent.TButton",
        command=lambda: self.new_window(Win2)
        )
        self.accentbutton.grid(row=7, column=0, padx=5, pady=10, sticky="nsew")


    def new_window(self,winclass):
        if self.win2_status == 0:
            try:
                if self.win2.status == 'normal': # if it's not created yet
                    self.win2.focus_force()
            except:
                    self.win2 = tk.Toplevel(root) # create
                    Win2(self.win2) # populate
                    self.win2_status = 1

class Win2:
    def __init__(self, _root):
        self.root = _root
        self.root.geometry("300x300+500+200")
        self.root["bg"] = "navy"
        self.root.protocol("WM_DELETE_WINDOW", self.close)

    def close(self):
        print("Window destroyed")
        app.win2_status = 0
        self.root.destroy()


if __name__ == "__main__":
    root = tk.Tk()
    root.title("Azure dark theme")

    # Simply set the theme
    root.tk.call("source", "azure.tcl")
    root.tk.call("set_theme", "dark")

    app = App(root)
    app.pack(fill="both", expand=True)

    # Set a minsize for the window, and place it in the middle
    root.update()
    root.minsize(root.winfo_width(), root.winfo_height())
    x_cordinate = int((root.winfo_screenwidth() / 2) - (root.winfo_width() / 2))
    y_cordinate = int((root.winfo_screenheight() / 2) - (root.winfo_height() / 2))
    root.geometry("+{}+{}".format(x_cordinate, y_cordinate-20))

    root.mainloop()

Here is the output


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.