2

I have a large code where a button press is supposed to run a code that will take roughly 15 seconds to complete. Within this time I want to display a label that says "Processing, please wait" or something of that sort. However in python, the whole GUI created using tkinter will freeze and unfreeze once the procedure is over. How do I get around to doing this? I created a smaller code so that I can explain easier.

from tkinter import *
from threading import Thread
import os
import sys
import time

master = Tk()
master.geometry("500x500")
master.resizable(False,False)

def tryout():
    sign2.config(text = "AAA")
    for x in range(5):
        print(x)
        time.sleep(1)
    sign2.config(text = "BBB")
    for x in range(5):
        print(x)
        time.sleep(1)
    sign2.config(text = "CCC")

def close_window(): 
    master.destroy()
    sys.exit()

sign1 = Label(master, text = "VNA GUI").grid(pady=10, padx=10)
sign2 = Label(master, text = "Choose option to continue")
sign2.grid(pady=10, padx=10, ipadx=50)
Button(master, text='Exit', command=close_window).grid(pady=10, padx=20)
butTest = Button(master, text='test', command=tryout)
butTest.grid(pady=10, padx=20)

master.mainloop( )

So in this code I expect to see 'AAA' on the label first, followed by 'BBB' at the middle of the count from 0 to 4, and then 'CCC' at the end of the final count from 0 to 4. What happens here is the GUI freezes at the beginning, the count carries on and I just see 'CCC'. How do I get around this?

C Vith
  • 101
  • 3
  • 11
  • 2
    Perhaps you could use threading. (if you're thinking "I _am_ using threading, I imported it right at the top there", that is a necessary but not sufficient part of the process of using threading. You need to, among other things, also create a Thread object.) – Kevin May 04 '18 at 13:02
  • @Kevin yes you are right, the 'threading' I imported at the top was when I was experimenting with it earlier but forgot to remove it before uploading the code here. – C Vith May 05 '18 at 02:42

2 Answers2

4

There are only a few changes necessary to do that with threading.

First create a function start_tryout:

def start_tryout():
    Thread(target=tryout, daemon=True).start() # deamon=True is important so that you can close the program correctly

Then create the button with the new command:

butTest = Button(master, text='test', command=start_tryout)

Then it should no longer freeze the gui and you should be able to see the label change.

MegaIng
  • 7,361
  • 1
  • 22
  • 35
  • This mthod did in fact work, thanks! I suppose I just needed to understand how threading works in python and also importantly in tkinter. BTW if I wanted to thread another function, then I need to create a different thread for that right? – C Vith May 07 '18 at 05:25
  • @CVith Yes. One thread for every function that should run parallel. – MegaIng May 07 '18 at 06:09
3

You can try threading. I've made changes below to the code and tested it here, and it worked.

from tkinter import *
from threading import Thread
import os
import sys
import time
import threading  # NEW

master = Tk()
master.geometry("500x500")
master.resizable(False,False)

def tryout():
    sign2.config(text = "AAA")
    for x in range(5):
        print(x)
        time.sleep(1)
    sign2.config(text = "BBB")
    for x in range(5):
        print(x)
        time.sleep(1)
    sign2.config(text = "CCC")

def close_window():
    master.destroy()
    sys.exit()

def thread(): # NEW
    threading.Thread(target=tryout).start() # NEW


sign1 = Label(master, text = "VNA GUI").grid(pady=10, padx=10)
sign2 = Label(master, text = "Choose option to continue")
sign2.grid(pady=10, padx=10, ipadx=50)    
Button(master, text='Exit', command=close_window).grid(pady=10, padx=20)
butTest = Button(master, text='test', command=thread)  # Changed
butTest.grid(pady=10, padx=20)

master.mainloop( )
Saturate
  • 105
  • 1
  • 8
  • Yes this method worked. It was quite difficult to find a proper threading example involving tkinter buttons. Thanks! – C Vith May 07 '18 at 05:21