-1

I am trying to set up a simple python app which would tell the time in the format HH:MM:SS, to do it I set up a variable representing the time and another one representing the formatted time using strftime, and creating a label which would return it constantly. Since I implemented datetime now instead of datetime today so the value representing the hour (should) constantly change. But I do not know how to make the label update itself as well (preferably in sync with the hour change). I managed to get a incomplete solution, by creating a loop for the whole program using "whiletrue" statement, but the only thing it does is to show another window with the updated time as soon as I close the former. I also looked at other posts in the forum which told me to use after() function but the program returns an error which says it doesn't recognize config. This is my code:

while True:
    from datetime import *
    from tkinter import *
    window = Tk()
    window.title = ('Hour')
    #Implementation of a derived class defining tz

    class montréal(tzinfo) :
        _offset = timedelta(seconds = -18000)
        _name = "-0500"
        _dst = timedelta(0)        
        def utcoffset(self, dt):
            return self.__class__._offset
        def tzname(self, dt):
            return self.__class__._name
        def dst(self, dt):
            return self.__class__._dst
        def fromutc(self, dt):
        # raise ValueError error if dt.tzinfo is not self
            dtoff = dt.utcoffset()
            dtdst = dt.dst()
        # raise ValueError if dtoff is None or dtdst is None
            delta = dtoff - dtdst  # this is self's standard offset
            if delta:
                dt += delta   # convert to standard local time
                dtdst = dt.dst()
                # raise ValueError if dtdst is None
            if dtdst:
                return dt + dtdst
            else:
                return dt

    tz = montréal()

    actualTime = datetime.now(tz)

    #Defining the parameters for the new template

    actualHour = actualTime.strftime('%H')

    actualMinute = actualTime.strftime('%M')

    actualSecond= actualTime.strftime('%S')

    #Setting the template in a human-understandable way

    hourTemplate = actualHour,':',actualMinute,':',actualSecond

    hour= StringVar()

    hour.set(hourTemplate)

    #setting the Label widget 

    cadran = Label(window, textvariable=hour).pack(padx = 300, pady = 20)

    def hour_after():
        hour_updated = actualTime
        cadran.config(textvariable=hour_updated)
        window.after(1000,hour_after)

    hour_after()

    #closing statement
    window.mainloop()

and the error message I get is the following:

Traceback (most recent call last):
  File "/Users/louiscouture/Documents/heure.py", line 62, in <module>
    hour_after()
  File "/Users/louiscouture/Documents/heure.py", line 59, in hour_after
    cadran.config(textvariable=hour_updated)
AttributeError: 'NoneType' object has no attribute 'config'
Louis Couture
  • 72
  • 1
  • 9
  • different [examples to display current time using after](https://github.com/furas/python-examples/tree/master/tkinter/timer-using-after) – furas Jan 13 '18 at 20:55
  • error shows that `cadran` is `None` so you have to check where did you assign `None` to `cadran` – furas Jan 13 '18 at 20:56
  • there is no sense to import inside `while` because Python it will import it only once - and it is less readable. Using `while True` to create `Tk()` again and again makes no sense too. – furas Jan 13 '18 at 21:00
  • BTW: using `*` in `from datetime import *` and (other imports) is not prefered - and this is why I use `import datetime` and `datetime.tzinfo` – furas Jan 13 '18 at 22:43

1 Answers1

0

Common mistake

cadran = Label().pack()

you assign None to cadran because pack() returns None.

You have to do it in two lines

cadran = Label()
cadran.pack()

EDIT: working code (but I don't know why you use __class__ in class Montreal)

import tkinter as tk
import datetime

# --- classes --- (CamelCaseNames without native chars)

class Montreal(datetime.tzinfo) :

    _offset = datetime.timedelta(seconds = -18000)
    _name = "-0500"
    _dst = datetime.timedelta(0)        

    def utcoffset(self, dt):
        return self.__class__._offset

    def tzname(self, dt):
        return self.__class__._name

    def dst(self, dt):
        return self.__class__._dst

    def fromutc(self, dt):
        # raise ValueError error if dt.tzinfo is not self
        dtoff = dt.utcoffset()
        dtdst = dt.dst()
        # raise ValueError if dtoff is None or dtdst is None
        delta = dtoff - dtdst  # this is self's standard offset
        if delta:
            dt += delta   # convert to standard local time
            dtdst = dt.dst()
            # raise ValueError if dtdst is None

        if dtdst:
            return dt + dtdst
        else:
            return dt


# --- functions ---

def hour_after():
    actualTime = datetime.now(tz)
    cadran['text'] = actualTime.strftime('%H:%M:%S')
    window.after(1000, hour_after)

# --- main ---

tz = Montreal()

window = tk.Tk()
window.title = 'Hour' # you don't need `( )`

cadran = tk.Label(window)
cadran.pack(padx=300, pady=20)

hour_after()

window.mainloop()
furas
  • 134,197
  • 12
  • 106
  • 148