Search code examples
pythonmultithreadingtkinterpython-multithreadingsoftware-design

What is the best way to stop a thread and avoid 'RuntimeError' in python using threading and tkinter modules?


I have went through multiple solutions on the net, but they require a lot of code that might get confusing once you scale up. Is there a simple way to stop the thread and avoid the RuntimeError: threads can only be started once, in order to call the thread an infinite number of times. Here is a simple version of my code:

import tkinter
import time
import threading

def func():

    entry.config(state='disabled')
    label.configure(text="Standby for  seconds")
    time.sleep(3)
    sum = 0
    for i in range(int(entry.get())):
        time.sleep(0.5)
        sum = sum+i
        label.configure(text=str(sum))
    entry.config(state='normal')

mainwindow = tkinter.Tk()
mainwindow.title('Sum up to any number')

entry = tkinter.Entry(mainwindow)
entry.pack()
label = tkinter.Label(mainwindow, text = "Enter an integer",font=("Arial",33))
label.pack()

print(entry.get())

button = tkinter.Button(mainwindow, text="Press me", command=threading.Thread(target=func).start)
button.pack()

Solution

  • While this is a simple way that get things done, in a fewer lines of code. I couldn't use the .join() method. But, it seems that the app isn't creating any new threads. This is obvious through threading.active_counts() method. Here is the code below:

    import tkinter, threading, time
    
    def calc():
        entry.config(state='disabled')
        label.configure(text="Standby for 3 seconds")
        time.sleep(3)
        sum = 0
        for i in range(int(entry.get())):
            time.sleep(0.5)
            sum = sum+i
            labelnum.configure(text=str(sum))
        button.config(state='normal')
        label.configure(text="Sum up to any number")
        entry.config(state='normal')
    
    def func():
        t = threading.Thread(target=calc)
        t.start()
        #del t
        print('Active threads:',threading.active_count())
    
    
    mainwindow = tkinter.Tk()
    mainwindow.title('Sum up to any number')
    entry = tkinter.Entry(mainwindow)
    entry.pack()
    label = tkinter.Label(mainwindow, text = "Enter an integer",font=("Arial",33))
    label.pack()
    labelnum = tkinter.Label(mainwindow, text="",font=('Arial',33))
    labelnum.pack()
    button = tkinter.Button(mainwindow, text="Press me", command=func)
    button.pack()
    mainwindow.mainloop()