-1

here is my sample code:

from time import  sleep
import tkinter as tk
import threading


class Action:

    counter = 0

    def do_something(self):
        while True:
            print('Looping')
            sleep(5)


action = Action()
root = tk.Tk()

button = tk.Button(root, text='pressme harder', command=threading.Thread(target=action.do_something()).start())
button.grid(row=1, column=0)

root.mainloop()

What am I expecting? I'm expecting that as soon as I click the button in the UI an new thread is running, which is looping in the background and does not interfere with the UI (or later maybe other threads doing tasks in the background)

What is really happening? When running the code, the method of the class is executeds immdiately and locking the procedure. root.mainloop() is never reached and therefore no UI is drawn

Alternatively I tried the following change:

button = tk.Button(root, text='pressme harder', command=threading.Thread(target=lambda: action.do_something()).start())

This behaves in the following (imho wrong) way: The method is also called immediately, without pressing the button. This time the UI is drawn but seems the be locked by the thread (UI is slow/stuttering, pressing the buttom does not work most of the time)

Any Idea whats wrong there? Or how do I handle this in a more stable way?

Dakkar
  • 5,682
  • 5
  • 22
  • 28
  • 1
    The [duplicate question](https://stackoverflow.com/q/5767228/16775594) is linked to in my profile. Yes, it may be hard to spot at first, but you're calling `start()` immediately, not when the button is pressed. – Sylvester Kruin Feb 22 '22 at 18:58

1 Answers1

2

You shouldn't try to start a thread directly in the button command. I suggest you create another function that launches the thread.

from time import sleep
import tkinter as tk
import threading


class Action:
    counter = 0
    def do_something(self):
        while True:
            print('Looping')
            sleep(2)
            print("Finished looping")
            
    def start_thread(self):
        thread = threading.Thread(target=self.do_something, daemon=True)
        thread.start()


action = Action()
root = tk.Tk()

button = tk.Button(root, text='pressme harder', command=action.start_thread)
button.grid(row=1, column=0)

root.mainloop()
  • this basically helped. I had to use an lambda function additionally: `button = tk.Button(root, command=lamnda: action.start_thread)` because I had to pass parameter to the method. (see the comment of sylvester-kruin under my question) – Dakkar Feb 22 '22 at 20:10