0
votes

I am trying to stop the main window from running until a button has been pressed on a separate Toplevel window.

Example:

from tkinter import *

let_user_through = False

window = Tk()

def activate_main_window():
    global let_user_through
    let_user_through = True

frame = Toplevel()
b = Button(frame, text="Enter", command=activate_main_window).pack()


if let_user_through == True:
    lbl = Label(window, text="Hello")
    #bunch of code
    #bunch of code


window.mainloop()

In this example, in the main window there is a label that reads: "Hello". But I don't want people to be able to see it if they haven't pressed the button on the frame

Once the user has pressed the button, the frame will destroy itself and the main window will continue executing a bunch of code.

I'm a beginner to tkinter so i'm not sure if the answer is obvious or not. Thanks!

2

2 Answers

1
votes

You can use frame.wait_window() to wait until frame is destroyed. Also you need to call frame.destroy() inside activate_main_window().

from tkinter import *

let_user_through = False

window = Tk()

def activate_main_window():
    global let_user_through
    let_user_through = True
    frame.destroy() # need to destroy frame

# wait for root window becomes visible
# otherwise "frame" may be open behind root window
window.wait_visibility()
frame = Toplevel()
Button(frame, text="Enter", command=activate_main_window).pack()

frame.grab_set() # capture keyboard/mouse events
frame.wait_window() # wait for "frame" to be destroyed

if let_user_through:
    Label(window, text="Hello").pack()
    #bunch of code
    #bunch of code

# should it be within the above for loop?
window.mainloop()
0
votes

A small change to your code using window.withdraw and window.deiconify works for me. @acw1668 correctly pointed out an error in my original code, so here is the fix.

Your main window is invisible until user presses button.


import tkinter as tk

let_user_through = False

window = tk.Tk()
window.withdraw()

def activate_main_window():
    global let_user_through
    let_user_through = True
    frame.destroy() # need to destroy frame

frame = tk.Toplevel()
tk.Button(frame, text="Enter", command=activate_main_window).pack()

frame.wait_window() # wait for "frame" to be destroyed

if let_user_through:
    tk.Label(window, text="Hello").pack()
    window.update()
    window.deiconify()
    
    #bunch of code
    #bunch of code

window.mainloop()

I've created a class that removes the need for let_user_through and sets up code for any next steps.


import tkinter as tk

class invisible:

    def __init__( self ):

        self.window = tk.Tk()
        self.window.withdraw() # make window invisible

        self.frame = tk.Toplevel()
        tk.Button(
            self.frame, text = "Enter", command = self.activate_main_window ).pack( fill='both' )
        self.frame.wait_window( ) # wait for "frame"

        self.button = tk.Button( self.window, text = "Hello", command = self.remove_next )
        self.button.pack( fill = 'both')
        self.window.update()
        self.window.deiconify() # make window visible

    def activate_main_window( self ):

        self.frame.destroy() # need to destroy frame

    def remove_next( self ):

        self.button.destroy()

        tk.Label( self.window, text = "Bunch of codeA" ).pack( fill = 'both' )
        tk.Label( self.window, text = "Bunch of codeB" ).pack( fill = 'both' )
        tk.Label( self.window, text = "Bunch of codeC" ).pack( fill = 'both' )
        # continue code initialization

if __name__ == '__main__':

    make = invisible()
    tk.mainloop()