-1

My question is how to configure this basic clock code, to make it count backward (or down) from a specific time (like 48 hours), instead of count forward like a regular clock as it currently does.

import tkinter as tk
import time
class App():

    def __init__(self):
        self.root = tk.Tk()
        self.label = tk.Label(text="")
        self.label.pack()
        self.update_clock()
        self.root.mainloop

    def update_clock(self):
        now = time.strftime("%H:%M:%S")
        self.label.configure(text=now)
        self.root.after(1000, self.update_clock)

app=App()
Nae
  • 14,209
  • 7
  • 52
  • 79
WeimTime
  • 11
  • 2
  • Assuming [this](https://stackoverflow.com/q/2400262/7032856) didn't help you. – Nae Jan 04 '18 at 21:49
  • The code above is _incomplete_ as it doesn't produce a GUI. Perhaps you may want to replace `self.root.mainloop` with `self.root.mainloop()`. – Nae Jan 04 '18 at 22:27

1 Answers1

0

Below is a class, CountdowLabel, that takes seconds as input and starts counting down and displaying the time left immediately:

import tkinter as tk
import datetime as dt


class CountdownLabel(tk.Label):
    """ A Label in the format of HH:MM:SS, that displays counting down from given 
    seconds.
    """

    def __init__(self, master, seconds_left):
        super().__init__(master)
        self._seconds_left = seconds_left
        self._timer_on = False
        self._countdown()                   # Start counting down immediately

    def _start_countdown(self):
        self._stop_countdown()
        self._countdown()

    def _stop_countdown(self):
        if self._timer_on:
            self.after_cancel(self._timer_on)
            self._timer_on = False

    def _countdown(self):
        self['text'] = self._get_timedelta_from_seconds(self._seconds_left)
        if self._seconds_left:
            self._seconds_left -= 1
            self._timer_on = self.after(1000, self._countdown)

    @staticmethod
    def _get_timedelta_from_seconds(seconds):
        return dt.timedelta(seconds=seconds)


if __name__ == '__main__':
    root = tk.Tk()

    countdown = CountdownLabel(root, 3)
    countdown.pack()

    root.mainloop()

Below is a class,Countdown, that takes seconds as input from an entry, and starts counting down when the "Start" button is pressed, while displaying the time left on a label. To convert seconds to time format this answer, and to reset the timer this answer were very useful.

import tkinter as tk
import datetime

class Countdown(tk.Frame):
    '''A Frame with label to show the time left, an entry to input the seconds to count
    down from, and a start button to start counting down.'''
    def __init__(self, master):
        super().__init__(master)
        self.create_widgets()
        self.show_widgets()
        self.seconds_left = 0
        self._timer_on = False

    def show_widgets(self):

        self.label.pack()
        self.entry.pack()
        self.start.pack()

    def create_widgets(self):

        self.label = tk.Label(self, text="00:00:00")
        self.entry = tk.Entry(self, justify='center')
        self.entry.focus_set()
        self.start = tk.Button(self, text="Start", command=self.start_button)

    def countdown(self):
        '''Update label based on the time left.'''
        self.label['text'] = self.convert_seconds_left_to_time()

        if self.seconds_left:
            self.seconds_left -= 1
            self._timer_on = self.after(1000, self.countdown)
        else:
            self._timer_on = False

    def start_button(self):
        '''Start counting down.'''
        self.seconds_left = int(self.entry.get())   # 1. to fetch the seconds
        self.stop_timer()                           # 2. to prevent having multiple
        self.countdown()                            #    timers at once

    def stop_timer(self):
        '''Stops after schedule from executing.'''
        if self._timer_on:
            self.after_cancel(self._timer_on)
            self._timer_on = False

    def convert_seconds_left_to_time(self):

        return datetime.timedelta(seconds=self.seconds_left)


if __name__ == '__main__':
    root = tk.Tk()
    root.resizable(False, False)

    countdown = Countdown(root)
    countdown.pack()

    root.mainloop()
Nae
  • 14,209
  • 7
  • 52
  • 79
  • Thank you for this. I have been playing around with it over the last couple days. What could I do to make this start by itself WITHOUT the click of a start button and it merely starts without any input? I have already defined a specific time for it to start, now I just need it to start by itself upon launching the python program. – WeimTime Jan 06 '18 at 22:19
  • @WeimTime See above example. – Nae Jan 07 '18 at 19:50