Dreaded Harvester
Dreaded Harvester

Reputation: 1547

How to remove button in Tkinter while the function called on clicking it is still under execution?

I used tkinter to create a button and assigned a function to it using command parameter. But this function contains some code takes time to execute. I have simulated it here using time.sleep(). I want to remove this button when this button is clicked. For this I called the global variable for button inside the function and then used pack_forget().

from tkinter import *
import time


def signIn():
    global login_button
    login_button.pack_forget()
    # code after this takes some time to run.
    time.sleep(10)


login_screen = Tk()
login_button = Button(login_screen, text="Login", width=10, height=1, command=signIn)
login_button.pack()
login_screen.mainloop() 

But the problem is that button gets removed only after the function execution is complete (i.e after 10 seconds). Is there any way I can get the button removed as soon as the pack_forget() line gets executed and not wait for the full function to complete execution?

Upvotes: 2

Views: 727

Answers (3)

T Randolph
T Randolph

Reputation: 11

This worked for me in that situation.

def launch_button(*args):
    # button will show new text when this function is done. The second argument
    # is the new text we're sending to the button
    data_button_widget.configure(text=args[1])
    # schedule launch of the next function, 1 ms after returning to mainloop -
    # The first argument is the function to launch
    data_button_widget.after(1, args[0])


def get_data(*args):
    # button will reconfigure to original text when this function is done
    data_button_widget.configure(text='Original button text')
    <code that takes some time here>

# make a window
wndw = Tk()

# add a frame widget to the window
fram = ttk.Frame(wndw, padding=SM_PAD)
fram.grid(column=0, row=0)
wndw.columnconfigure(0, weight=1)
wndw.rowconfigure(0, weight=1)

# make a button widget
data_button_widget = ttk.Button(fram, command=lambda: launch_button(get_data, 'wait...'))
data_button_widget.grid(column=2, row=4, padx=SM_PAD, pady=LG_PAD)
data_button_widget.configure(text='Original button text')

# start mainloop
wndw.mainloop()

Upvotes: 1

Dreaded Harvester
Dreaded Harvester

Reputation: 1547

Using update() works:

def signIn():
    global login_button, login_screen
    login_button.pack_forget()
    login_screen.update()
    # code after this takes some time to run.
    time.sleep(10)

Upvotes: 0

Bitto
Bitto

Reputation: 8245

Call update_idletasks method of the login_screen window after removing the button.

From effbot:

update_idletasks()

Calls all pending idle tasks, without processing any other events. This can be used to carry out geometry management and redraw widgets if necessary, without calling any callbacks.

def signIn():
    global login_button, login_screen
    login_button.pack_forget()
    login_screen.update_idletasks()
    # code after this takes some time to run.
    time.sleep(10)

Upvotes: 2

Related Questions