0

I'm in the progress of writing a python app to show a countdown clock in one window, and a video in another (haven't started integrating the video part yet).

However, the countdown clock I have written doesn't update, and only shows the initial countdown time when the app was launched. I need it to update around every 500ms.

This is the area of interest in my code PageOne & show_clock. PageOne is the display frame which should update to show a live clock countdown.

EDIT: Code has been updated since original post. Now I don't get the clock label updating at all. I'm experiencing the following errors:

Line 73 : Statement seems to have no effect
It looks like the statement doesnt have (or at least seems to) any effect.
Line 108 : Name 'show_time' is not defined
class PageOne(tk.Frame):

def __init__(self, parent, controller):
    
    tk.Frame.__init__(self, parent)
    self.controller = controller
    fnt = font.Font(family='Quicksand Medium', size=30)
    
    self.txt = tk.StringVar()
    self.show_time
    
    lbl = tk.Label(self, textvariable=self.txt, font=fnt, foreground="black", background="#FFFFDD")
    lbl.pack()
    button = tk.Button(self, text="Go to the start page",
                       command=lambda: controller.show_frame("StartPage"))
    button.pack()

def show_time(self):
    endTime = datetime.datetime(2029, 7, 20, 16, 0, 0)
    # Get the time remaining until the event
    remainder = endTime - datetime.datetime.now()
    # remove the microseconds part
    remainder = remainder - datetime.timedelta(microseconds=remainder.microseconds)

    yrs = remainder.days // 365
    yrsTxt = ' years, '
    if yrs == 1:
        yrsTxt = ' year, '

    days = remainder.days % 365
    daysTxt = ' days,'
    if days == 1:
    daysTxt = ' day,'

    timeTxt = str(remainder).split(',')[1]

    # Show the time left
    global myClock
    myClock = str(yrs) + yrsTxt + str(days) + daysTxt + timeTxt
    
    # Show the time left
    self.txt.set(f"{yrs} {yrsTxt}, {days} {daysTxt}, {timeTxt}")
    
    self.after(1000, show_time)
Newbie
  • 1,160
  • 2
  • 11
  • 24
  • You've posted too much code. Please try to narrow the code down to a [mcve]. That being said, when you do something like `self.after(500, show_time())`, it immediately calls `show_time()` rather than waiting 500ms. `after` requires a callable. – Bryan Oakley Mar 21 '23 at 15:33
  • I have edited the code to be more concise. So, how would I use after to loop rather than call once? – Newbie Mar 21 '23 at 15:45
  • [Have look at this Q&A](https://stackoverflow.com/a/63118515/13629335) – Thingamabobs Mar 22 '23 at 08:45
  • So I've updated the code to call update_clock which repeats, which updates the label StringVar. However, it still doesn't update? – Newbie Mar 23 '23 at 10:49
  • I think I've narrowed down the issue, please see my edit in the main post. – Newbie Mar 23 '23 at 10:56

1 Answers1

1

You need to use instance variable instead of local variable if the variable will be accessed across functions. Also you need to prefix self. when calling class methods.

Below is the modified code:

class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        self.controller = controller
        fnt = font.Font(family='Quicksand Medium', size=30)

        self.txt = tk.StringVar() # use instance variable instead
        lbl = tk.Label(self, textvariable=self.txt, font=fnt,
                       foreground="black", background="#FFFFDD")
        lbl.pack()

        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.pack()

        self.update_clock() # start updating clock


    def update_clock(self):
        self.show_time()
        self.after(1000, self.update_clock)


    def show_time(self): # added self argument
        endTime = datetime.datetime(2029, 7, 20, 16, 0, 0)
        # Get the time remaining until the event
        remainder = endTime - datetime.datetime.now()
        # remove the microseconds part
        remainder -= datetime.timedelta(microseconds=remainder.microseconds)

        yrs, days = divmod(remainder.days, 365)
        yrsTxt = "years" if yrs > 1 else "year"
        daysTxt = "days" if days > 1 else "day"
        timeTxt = str(remainder).split(',')[1]

        # Show the time left
        self.txt.set(f"{yrs} {yrsTxt}, {days} {daysTxt}, {timeTxt}")

Note that you can combine update_clock() and show_time() into one function for your case.

acw1668
  • 40,144
  • 5
  • 22
  • 34
  • Hi, I've implimented your changes, but I'm getting a lot of warnings. Please see the main post. – Newbie Mar 23 '23 at 11:57
  • Note that your code has indentation issue. Also `update_clock()` and `show_time()` are class methods in my code. Make sure you have followed my changes. – acw1668 Mar 23 '23 at 12:08