UnityNewb
UnityNewb

Reputation: 361

Python Tkinter While Thread

Well i am a bit of newb at python, and i am getting hard to make a thread in Tkinter , as you all know using while in Tkinter makes it Not Responding and the script still running.

  def scheduler():
    def wait():
        schedule.run_pending()
        time.sleep(1)
        return
    Hours = ScheduleTest()
    if len(Hours) == 0:
        print("You need to write Hours, Example: 13:30,20:07")
    if len(Hours) > 0:
        print("Scheduled: ", str(Hours))
        if len(Hours) == 1:
            schedule.every().day.at(Hours[0]).do(Jumper)
            print("Will jump 1 time")
        elif len(Hours) == 2:
            schedule.every().day.at(Hours[0]).do(Jumper)
            schedule.every().day.at(Hours[1]).do(Jumper)
            print("Will jump 2 times")
        elif len(Hours) == 3:
            schedule.every().day.at(Hours[0]).do(Jumper)
            schedule.every().day.at(Hours[1]).do(Jumper)
            schedule.every().day.at(Hours[2]).do(Jumper)
            print("Will jump 3 times")
        while True:
            t = threading.Thread(target=wait)
            t.start()
    return
scheduler()

i have tried to do something like this but it still makes tkinter not responding Thanks in advance.

Upvotes: 1

Views: 2187

Answers (1)

Jacob Vlijm
Jacob Vlijm

Reputation: 3159

When to use the after method; faking while without threading

As mentioned in a comment, In far most cases, you do not need threading to run a "fake" while loop. You can use the after() method to schedule your actions, using tkinter's mainloop as a "coat rack" to schedule things, pretty much exactly like you would in a while loop.

This works in all situations where you can simply throw out commands with e.g. subprocess.Popen(), update widgets, show messages etc.

It does not work when the scheduled process takes a lot of time, running inside the mainloop. Therefore time.sleep() is a bummer; it will simply hold the mainloop.

How it works

Within that limitation however, you can run complicated tasks, schedule actions even set break (-equivalent) conditions.

Simply create a function, initiate it with window.after(0, <function>). Inside the function, (re-) schedule the function with window.after(<time_in_milliseconds>, <function>).

To apply a break- like condition, simply rout the process (inside the function) not to be scheduled again.

An example

This is best illustrated with a simplified example:

enter image description here

enter image description here

enter image description here

from tkinter import *
import time

class TestWhile:
    
    def __init__(self):
        
        self.window = Tk()
        shape = Canvas(width=200, height=0).grid(column=0, row=0)
        self.showtext = Label(text="Wait and see...")
        self.showtext.grid(column=0, row=1)
        fakebutton = Button(
            text="Useless button"
            )
        fakebutton.grid(column=0, row=2)
        
        # initiate fake while
        self.window.after(0, self.fakewhile)
        self.cycles = 0
       
        self.window.minsize(width=200, height=50)
        self.window.title("Test 123(4)")
        self.window.mainloop()

    def fakewhile(self):
        # You can schedule anything in here
        if self.cycles == 5:
            self.showtext.configure(text="Five seconds passed")
        elif self.cycles == 10:
            self.showtext.configure(text="Ten seconds passed...")
        elif self.cycles == 15:
            self.showtext.configure(text="I quit...")
        """
        If the fake while loop should only run a limited number of times,
        add a counter
        """
        self.cycles = self.cycles+1
        """
        Since we do not use while, break will not work, but simply
        "routing" the loop to not being scheduled is equivalent to "break":
        """
        if self.cycles <= 15:
            self.window.after(1000, self.fakewhile)
        else:
            # start over again
            self.cycles = 0
            self.window.after(1000, self.fakewhile)
            # or: fakebreak, in that case, uncomment below and comment out the
            # two lines above
            # pass

TestWhile()

In the example above, we run a scheduled process for fifteen seconds. While the loop runs, several simple tasks are performed, in time, by the function fakewhile().

After these fivteen seconds, we can start over again or "break". Just uncomment the indicated section to see...

Upvotes: 5

Related Questions