g0dst3r
g0dst3r

Reputation: 69

Open only one Tk.Toplevel window

I bound the opening of a new window (Tk.Toplevel) on a button. However, if I press the button twice, two windows turn on. Can I deactivate the button until the new window is turned off, or display a message box if I press the button twice ?

Upvotes: 1

Views: 1254

Answers (2)

furas
furas

Reputation: 142641

You can disable/enable button or you can assign TopLevel to global variable which at start has value None and you check if it is still None before creating window. if it is not None then don't create window. When you close window then you set it again None.

This method can be use for any object which can be only one at some moment - ie. bullet in game.

import tkinter as tk  # PEP8: `import *` is not preferred

# --- functions ---

def close_top():
    global single_top

    single_top.destroy()
    single_top = None
    
def open_top():
    global single_top
    
    if single_top is None:
        single_top = tk.Toplevel(root)
        l = tk.Label(single_top, text='TopLevel')
        l.pack()    
        single_top.protocol("WM_DELETE_WINDOW", close_top)
    else:
        print("Top level already exists")
    
# --- main ---

single_top = None

root = tk.Tk()

b = tk.Button(root, text='TOP', command=open_top)
b.pack()

root.mainloop()

EDIT:

The same structure with disabled button

import tkinter as tk  # PEP8: `import *` is not preferred

# --- functions ---

def close_top():

    single_top.destroy()

    b['state'] = 'normal'
    
def open_top():
    global single_top

    b['state'] = 'disable'
    
    single_top = tk.Toplevel(root)
    l = tk.Label(single_top, text='TopLevel')
    l.pack()    
    single_top.protocol("WM_DELETE_WINDOW", close_top)
    
# --- main ---

root = tk.Tk()

b = tk.Button(root, text='TOP', command=open_top)
b.pack()

root.mainloop()

Upvotes: 2

JacksonPro
JacksonPro

Reputation: 3275

If you don't want to import an external library. You can simply check if root contains any instance of Toplevel using isinstance().

Here is an example:

from tkinter import *
from tkinter import messagebox 


def top():
    
    if not any(isinstance(x, Toplevel) for x in root.winfo_children()):
            top = Toplevel(root)
            lbl = Label(top, text='TopLevel')
            lbl.pack()    
             
    else:
        
        messagebox.showinfo("showinfo", "Top level already exists")
        
    

root = Tk()

btn = Button(root, text='text', command=top)
btn.pack()

root.mainloop()

If you simply want to disable the button.

from tkinter import *
from tkinter import messagebox 


def top():

 
        btn['state'] = 'disabled'
        top = Toplevel(root)
        lbl = Label(top, text='TopLevel')
        lbl.pack()

        top.protocol("WM_DELETE_WINDOW", lambda : btn.configure(state='normal') or top.destroy())


                
root = Tk()

btn = Button(root, text='text', command=top)
btn.pack()

root.mainloop()

Upvotes: 6

Related Questions