Question

In my program I have a method in my GUI class that I want to update the GUI on a regular basis. Below is a simplified version of what my code does.

from tkinter import *
from time import sleep

class GUI_Class:
    def __init__(self, parent):
        self.var = IntVar()
        scale = Scale(parent, to = 1, variable = self.var)
        scale.pack()
        self.label = Label(parent, bg = "white")
        self.label.pack()
        button = Button(parent)
        button.pack()
        button.bind("<Button-1>",lambda event:self.change_colour()) 
    def change_colour(self):
        if self.var.get() == 1:
            counter = 0
            while self.var.get() == 1 and counter != 20:
                self.label.configure(bg = "red")
                self.label.update_idletasks()
                sleep(0.5)
                self.label.configure(bg = "blue")
                self.label.update_idletasks()
                sleep(0.5)
                counter += 1
        else:
            self.label.configure(bg = "white")

root = Tk()
GUI = GUI_Class(root) 
root.mainloop()

The problem is is that while the while loop for altering the GUI is running the program loses all functionality as it waits for the while loop to end. I've looked at the answers to other people questions and all the answers suggest threading however in the examples in the answers it is always the method of another class being run in a seperate thread. While I can create a separate class with commands reading GUI.label.configure(bg = "colour) and run it in it own thread the assessment this program is for states that there must be minimal interaction between classes, so having a class whose entire purpose is to change the layout of the GUI created in another class could lower my grade. What I want to know is if there is a way to run a method in a seperate thread to the class it belongs to and therefore have my while loop running while the rest of the GUI still operates i.e. while the label is flashing between blue and red The user can change the scale to 0, press the button and stop the loop?

Was it helpful?

Solution

Tkinter provides an after method that allows you to schedule a command to be run after some number of milliseconds. In the after handler you can check your state, make appropriate modifications and schedule another call to the same handler. This was you never block the running UI thread but arrange for a regular call to a method.

The after method returns a token that can be used to cancel the scheduled task. So provided you retain that token you can pass this to the after_cancel method to cancel an outstanding scheduled call.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top