Home > OS >  TKINTER: Howto auto-update loop generated labels
TKINTER: Howto auto-update loop generated labels

Time:08-08

I'm battling with tkinter's .after() functionality, and I see all the examples, these all work as demo in my environment if applied on a well-known amount of labels

The challenge I have here is that I have an unknown amount of labels generated by a loop.

I need to have these labels regenerated and overwritten every x seconds. The number of labels may change, text and color of the labels will change accordingly, as well.

I think the challenge here is to re-run the whole labels generation function _construct_label_colorise after x seconds, and have it replace previous labels.

Think of it as like these labels would be a list of windows processes, each time it constructs labels - some processes might go down and disappear, and some appear on top. so, every second the number of labels will be different. For this example, I limit the delta to 3-5.labels.

Please advise a way to correctly implement _construct_label_colorise function rerun, after x seconds intervals.

from tkinter import StringVar, Tk, Frame, Label, LabelFrame, mainloop
from platform import system
from random import randint

class Window(Tk):
    def __init__(self):
        super(Window, self).__init__()
        # self.geometry('100x150')
        self.build_ui()
        
    def build_ui(self):
        mainFrame = Frame(self)
        mainFrame.pack()
         
        status_frame = LabelFrame(mainFrame, text='EP status')
        status_frame.pack(padx=5,pady=5)
        self._construct_label_colorise(status_frame)
        self.after(1000,self._update_status(status_frame))
    
    #Note!: The number of LABELs delivered by this function in production changes dynamically, it is an unknown total label quantity at each refresh
    
    def _construct_label_colorise(self,master):
        self.label_list=[]
        for x in range(0,randint(3,5)):
            c = randint(0,1)
            fg = "green" if c == 0 else "red"
            label = StringVar
            label = Label(master, text=f'color {fg}', foreground= fg)
            label.pack(padx=5,pady=5)
            self.label_list.append (label)
        
    def _update_status(self,master):
        for label in self.label_list:
            label.destroy()
        self.after(1000,self._construct_label_colorise(master))
        pass
        
window = Window()
window.mainloop()

CodePudding user response:

When you use after, it will only use the callback once.

If you want to keep repeating an action, you have to re-schedule it with after every time.

CodePudding user response:

Note that self.after(1000, self._update_status(status_frame)) will execute self._update_status(status_frame) immediately, not 1000ms later. Also you don't need self._update_status() at all for your case.

...
from random import randint, choice

class Window(Tk):
    def __init__(self):
        super(Window, self).__init__()
        # self.geometry('100x150')
        self.build_ui()

    def build_ui(self):
        mainFrame = Frame(self)
        mainFrame.pack()

        status_frame = LabelFrame(mainFrame, text='EP status')
        status_frame.pack(padx=5,pady=5)

        self.label_list = []  # initialize the list here
        self._construct_label_colorise(status_frame)  # start the after loop

    #Note!: The number of LABELs delivered by this function in production changes dynamically, it is an unknown total label quantity at each refresh

    def _construct_label_colorise(self,master):
        # delete existing labels
        for label in self.label_list:
            label.destroy()
        # clear the list
        self.label_list.clear()
        # create random number of labels with random foreground color
        for x in range(0,randint(3,5)):
            fg = choice(["green", "red"])
            label = Label(master, text=f'color {fg}', foreground= fg)
            label.pack(padx=5,pady=5)
            self.label_list.append (label)
        # call this function one second later
        self.after(1000, self._construct_label_colorise, master)

...
  • Related