lucian_v
lucian_v

Reputation: 121

Tkinter update variable real time

I have this code which display a page and then when press PAGE1 button go to other frame. Here i want to display time in any of the labels but i want it update automatically. I couldn t manage do it myself

import Tkinter as tk
from Tkinter import *
import time
import datetime

def clock():
    time = datetime.datetime.now().strftime("Time: %H:%M:%S")
    print time

class MainApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (MainPage, page1, help):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame
            frame.grid(row=0, column=0, columnspan=12,sticky="nsew")
            frame.grid_columnconfigure(0, weight=1)
            frame.grid_columnconfigure(1, weight=1)
            frame.grid_columnconfigure(2, weight=1)
            frame.grid_columnconfigure(3, weight=1)
            frame.grid_columnconfigure(4, weight=1)
            frame.grid_columnconfigure(5, weight=1)
            frame.grid_columnconfigure(6, weight=1)
            frame.grid_columnconfigure(7, weight=1)
            frame.grid_columnconfigure(8, weight=1)
            frame.grid_columnconfigure(9, weight=1)
            frame.grid_columnconfigure(10, weight=1)
            frame.grid_columnconfigure(11, weight=1)

        self.show_frame("MainPage")
        clock()
    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()


class MainPage(tk.Frame):

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

        # line 0
        label00 = tk.Label(self, text='00', height=2)
        label00.configure(relief='raised')
        label00.grid(row=0, column=0, sticky='nsew', columnspan=12)
        # line 1
        label10 = tk.Label(self, text='10')
        label10.configure(relief='raised')
        label10.grid(row=1, column=0, sticky='nsew')
        label11 = tk.Label(self, text='LOGO')
        label11.configure(relief='raised')
        label11.grid(row=1, column=1, sticky='nsew', columnspan=4, rowspan=2)
        label12 = tk.Label(self, text='12')
        label12.configure(relief='raised')
        label12.grid(row=1, column=5, sticky='nsew')
        label13 = tk.Label(self, text='TITLE')
        label13.configure(relief='raised')
        label13.grid(row=1, column=6, sticky='nsew', columnspan=5)
        label14 = tk.Label(self, text='14')
        label14.configure(relief='raised')
        label14.grid(row=1, column=11, sticky='nsew')
        # line 2
        label20 = tk.Label(self, text='20')
        label20.configure(relief='raised')
        label20.grid(row=2, column=0, sticky='nsew')
        label21 = tk.Label(self, text='21')
        label21.configure(relief='raised')
        label21.grid(row=2, column=5, sticky='nsew')
        label22 = tk.Label(self, text='Desc')
        label22.configure(relief='raised')
        label22.grid(row=2, column=6, sticky='nsew', columnspan=5)
        label23 = tk.Label(self, text='23')
        label23.configure(relief='raised')
        label23.grid(row=2, column=11, sticky='nsew')
        # line 3
        label30 = tk.Label(self, text='30', height=2)
        label30.configure(relief='raised')
        label30.grid(row=3, column=0, sticky='nsew', columnspan=12)
        #line 4
        label40 = tk.Label(self, text='40', width=10)
        label40.configure(relief='raised')
        label40.grid(row=4, column=0, sticky='nsew')
        label41 = tk.Label(self, text='STATUS', font=("Helvetica", 16), justify='center', fg="blue")
        label41.configure(relief='raised')
        label41.grid(row=4, column=1, columnspan=10)
        label42 = tk.Label(self, text='42', width=10)
        label42.configure(relief='raised')
        label42.grid(row=4, column=11, sticky='nsew')
        #line 5
        label50 = tk.Label(self, text='50', height=2)
        label50.configure(relief='raised')
        label50.grid(row=5, column=0, columnspan=12, sticky="nsew")
        #line 6
        label60 = tk.Label(self, text='60', height=2)
        label60.configure(relief='raised')
        label60.grid(row=6, column=0, sticky='nsew')
        buttonauto = tk.Button(self, text="PAGE1", font=("Helvetica", 16), justify='center', width=40, height=5,
                              command=lambda: controller.show_frame("page1"))
        buttonauto.grid(row=6, column=1, columnspan=4)
        label61 = tk.Label(self, text='61', height=2)
        label61.configure(relief='raised')
        label61.grid(row=6, column=5, sticky='nsew')
        label62 = tk.Label(self, text='62', height=2)
        label62.configure(relief='raised')
        label62.grid(row=6, column=6, sticky='nsew')
        buttoncam = tk.Button(self, text="HELP",font=("Helvetica", 16), justify='center', width=40, height=5,
                              command=lambda: controller.show_frame("help"))
        buttoncam.grid(row=6 , column=7, columnspan=4)
        label63 = tk.Label(self, text='63', height=2)
        label63.configure(relief='raised')
        label63.grid(row=6, column=11, sticky='nsew')
        # line 7
        label70 = tk.Label(self, text='70', height=2)
        label70.configure(relief='raised')
        label70.grid(row=7, column=0, sticky='nsew', columnspan=12)

        #line 13
        label13 = tk.Label(self, text='', height=2)
        label13.configure(relief='raised')
        label13.grid(row=13, column=0, columnspan=12, sticky="nsew")
        #line 14
        label14 = tk.Label(self, text='', width=10)
        label14.grid(row=14, column=0, sticky='w')
        buttonhlp = tk.Button(self, text="Help", width=20, height = 3,
                              command=lambda: controller.show_frame("help"))
        buttonhlp.grid(row=14, column=1, columnspan=4)
        label14 = tk.Label(self, text='')
        label14.grid(row=14, column=5, columnspan=2)
        buttonquit = tk.Button(self, text="Quit", width=20, height = 3, command=close_window)
        buttonquit.grid(row=14, column=7, columnspan=4)
        label14 = tk.Label(self, text='', width=10)
        label14.grid(row=14, column=11, sticky='e')
        #line 15
        label15 = tk.Label(self, text='', height=5)
        label15.grid(row=15, column=0, columnspan=12, sticky="nsew")


class page1(tk.Frame):

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

        #line 0
        label00 = tk.Label(self, text='PAGE1', height=2)
        label00.configure(relief='raised')
        label00.grid(row=13, column=0, columnspan=12, sticky="nsew")
        #line 1
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=0, sticky='w')
        buttonback = tk.Button(self, text="Back", width=20, height = 3,
                              command=lambda: controller.show_frame("MainPage"))
        buttonback.grid(row=14, column=1, columnspan=4)
        label10= tk.Label(self, text='')
        label10.grid(row=14, column=5, columnspan=2)
        buttonquit = tk.Button(self, text="Quit", width=20, height = 3, command=close_window)
        buttonquit.grid(row=14, column=7, columnspan=4)
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=11, sticky='e')
        #line 2
        label20 = tk.Label(self, text='', height=5)
        label20.grid(row=15, column=0, columnspan=12, sticky="nsew")

class help(tk.Frame):

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

        #line 0
        label00 = tk.Label(self, text='HELP', height=2)
        label00.configure(relief='raised')
        label00.grid(row=13, column=0, columnspan=12, sticky="nsew")
        #line 1
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=0, sticky='w')
        buttonback = tk.Button(self, text="Back", width=20, height = 3,
                              command=lambda: controller.show_frame("MainPage"))
        buttonback.grid(row=14, column=1, columnspan=4)
        label10= tk.Label(self, text='')
        label10.grid(row=14, column=5, columnspan=2)
        buttonquit = tk.Button(self, text="Quit", width=20, height = 3, command=close_window)
        buttonquit.grid(row=14, column=7, columnspan=4)
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=11, sticky='e')
        #line 2
        label20 = tk.Label(self, text='', height=5)
        label20.grid(row=15, column=0, columnspan=12, sticky="nsew")


def close_window ():
    app.destroy()


if __name__ == "__main__":
    app = MainApp()

    app.overrideredirect(True)
    app.geometry("{0}x{1}+0+0".format(app.winfo_screenwidth(), app.winfo_screenheight()))
    app.focus_set()  # <-- move focus to this widget


    app.mainloop()

So actually I want that when open page1 frame, in label00 I want to see time that I print in the beginning of the code.

Upvotes: 0

Views: 11401

Answers (2)

martineau
martineau

Reputation: 123531

One way to do it would be to periodically call a function and update the GUI. In Tkinter this is usually done by using the universal widget method after.

I've modified your code to create a StringVar attribute to hold the time value and use after() to call a new clock() method which has also been added to your MainApp class. All this method does is update the StringVar attribute of the class instance.

The other thing I did was modify the __init__() method of the your Page1 class to use the textvariable option instead of the text option when creating the label00 widget, and to specify the StringVar attribute that was added to the MainApp class as its value.

The nice thing about doing this is the label will be updated automatically whenever the value of the variable changes. In addition, you can reference this same attribute from different parts of the GUI as needed.

Note I only modified the label00 attribute of your Page1 class...you'll need to do something similar to the other places you want the current time displayed. (They can all use the same StringVar attribute.)

import time
import datetime
import Tkinter as tk
from Tkinter import *

class MainApp(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.timevar = tk.StringVar()  # Added.

        self.frames = {}
        for F in (MainPage, Page1, Help):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame
            frame.grid(row=0, column=0, columnspan=12,sticky="nsew")
            frame.grid_columnconfigure(0, weight=1)
            frame.grid_columnconfigure(1, weight=1)
            frame.grid_columnconfigure(2, weight=1)
            frame.grid_columnconfigure(3, weight=1)
            frame.grid_columnconfigure(4, weight=1)
            frame.grid_columnconfigure(5, weight=1)
            frame.grid_columnconfigure(6, weight=1)
            frame.grid_columnconfigure(7, weight=1)
            frame.grid_columnconfigure(8, weight=1)
            frame.grid_columnconfigure(9, weight=1)
            frame.grid_columnconfigure(10, weight=1)
            frame.grid_columnconfigure(11, weight=1)

        # Synchronize with the computer's clock.
        snooze = (1000000 - datetime.datetime.now().microsecond) / 1000000.
        if snooze > 0:
            time.sleep(snooze)  # Sleep until next whole second.
        self.clock()  # Starts string variable update process.

        self.show_frame("MainPage")

    def show_frame(self, page_name):
        frame = self.frames[page_name]
        frame.tkraise()

    # Additional method added.
    def clock(self):
        self.timevar.set(datetime.datetime.now().strftime("Time: %H:%M:%S"))
        self.after(1000, self.clock)  # Update every second (1000 millsecs)


class MainPage(tk.Frame):

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

        # line 0
        label00 = tk.Label(self, text='00', height=2)
        label00.configure(relief='raised')
        label00.grid(row=0, column=0, sticky='nsew', columnspan=12)
        # line 1
        label10 = tk.Label(self, text='10')
        label10.configure(relief='raised')
        label10.grid(row=1, column=0, sticky='nsew')
        label11 = tk.Label(self, text='LOGO')
        label11.configure(relief='raised')
        label11.grid(row=1, column=1, sticky='nsew', columnspan=4, rowspan=2)
        label12 = tk.Label(self, text='12')
        label12.configure(relief='raised')
        label12.grid(row=1, column=5, sticky='nsew')
        label13 = tk.Label(self, text='TITLE')
        label13.configure(relief='raised')
        label13.grid(row=1, column=6, sticky='nsew', columnspan=5)
        label14 = tk.Label(self, text='14')
        label14.configure(relief='raised')
        label14.grid(row=1, column=11, sticky='nsew')
        # line 2
        label20 = tk.Label(self, text='20')
        label20.configure(relief='raised')
        label20.grid(row=2, column=0, sticky='nsew')
        label21 = tk.Label(self, text='21')
        label21.configure(relief='raised')
        label21.grid(row=2, column=5, sticky='nsew')
        label22 = tk.Label(self, text='Desc')
        label22.configure(relief='raised')
        label22.grid(row=2, column=6, sticky='nsew', columnspan=5)
        label23 = tk.Label(self, text='23')
        label23.configure(relief='raised')
        label23.grid(row=2, column=11, sticky='nsew')
        # line 3
        label30 = tk.Label(self, text='30', height=2)
        label30.configure(relief='raised')
        label30.grid(row=3, column=0, sticky='nsew', columnspan=12)
        #line 4
        label40 = tk.Label(self, text='40', width=10)
        label40.configure(relief='raised')
        label40.grid(row=4, column=0, sticky='nsew')
        label41 = tk.Label(self, text='STATUS', font=("Helvetica", 16), justify='center', fg="blue")
        label41.configure(relief='raised')
        label41.grid(row=4, column=1, columnspan=10)
        label42 = tk.Label(self, text='42', width=10)
        label42.configure(relief='raised')
        label42.grid(row=4, column=11, sticky='nsew')
        #line 5
        label50 = tk.Label(self, text='50', height=2)
        label50.configure(relief='raised')
        label50.grid(row=5, column=0, columnspan=12, sticky="nsew")
        #line 6
        label60 = tk.Label(self, text='60', height=2)
        label60.configure(relief='raised')
        label60.grid(row=6, column=0, sticky='nsew')
        buttonauto = tk.Button(self, text="PAGE1", font=("Helvetica", 16), justify='center', width=40, height=5,
                              command=lambda: controller.show_frame("Page1"))
        buttonauto.grid(row=6, column=1, columnspan=4)
        label61 = tk.Label(self, text='61', height=2)
        label61.configure(relief='raised')
        label61.grid(row=6, column=5, sticky='nsew')
        label62 = tk.Label(self, text='62', height=2)
        label62.configure(relief='raised')
        label62.grid(row=6, column=6, sticky='nsew')
        buttoncam = tk.Button(self, text="HELP",font=("Helvetica", 16), justify='center', width=40, height=5,
                              command=lambda: controller.show_frame("Help"))
        buttoncam.grid(row=6 , column=7, columnspan=4)
        label63 = tk.Label(self, text='63', height=2)
        label63.configure(relief='raised')
        label63.grid(row=6, column=11, sticky='nsew')
        # line 7
        label70 = tk.Label(self, text='70', height=2)
        label70.configure(relief='raised')
        label70.grid(row=7, column=0, sticky='nsew', columnspan=12)

        #line 13
        label13 = tk.Label(self, text='', height=2)
        label13.configure(relief='raised')
        label13.grid(row=13, column=0, columnspan=12, sticky="nsew")
        #line 14
        label14 = tk.Label(self, text='', width=10)
        label14.grid(row=14, column=0, sticky='w')
        buttonhlp = tk.Button(self, text="Help", width=20, height = 3,
                              command=lambda: controller.show_frame("Help"))
        buttonhlp.grid(row=14, column=1, columnspan=4)
        label14 = tk.Label(self, text='')
        label14.grid(row=14, column=5, columnspan=2)
        buttonquit = tk.Button(self, text="Quit", width=20, height = 3, command=close_window)
        buttonquit.grid(row=14, column=7, columnspan=4)
        label14 = tk.Label(self, text='', width=10)
        label14.grid(row=14, column=11, sticky='e')
        #line 15
        label15 = tk.Label(self, text='', height=5)
        label15.grid(row=15, column=0, columnspan=12, sticky="nsew")


class Page1(tk.Frame):

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

        #line 0
#        label00 = tk.Label(self, text='PAGE1', height=2)
        label00 = tk.Label(self, textvariable=controller.timevar, height=2)
        label00.configure(relief='raised')
        label00.grid(row=13, column=0, columnspan=12, sticky="nsew")
        #line 1
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=0, sticky='w')
        buttonback = tk.Button(self, text="Back", width=20, height = 3,
                              command=lambda: controller.show_frame("MainPage"))
        buttonback.grid(row=14, column=1, columnspan=4)
        label10= tk.Label(self, text='')
        label10.grid(row=14, column=5, columnspan=2)
        buttonquit = tk.Button(self, text="Quit", width=20, height = 3, command=close_window)
        buttonquit.grid(row=14, column=7, columnspan=4)
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=11, sticky='e')
        #line 2
        label20 = tk.Label(self, text='', height=5)
        label20.grid(row=15, column=0, columnspan=12, sticky="nsew")

class Help(tk.Frame):

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

        #line 0
        label00 = tk.Label(self, text='HELP', height=2)
        label00.configure(relief='raised')
        label00.grid(row=13, column=0, columnspan=12, sticky="nsew")
        #line 1
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=0, sticky='w')
        buttonback = tk.Button(self, text="Back", width=20, height = 3,
                              command=lambda: controller.show_frame("MainPage"))
        buttonback.grid(row=14, column=1, columnspan=4)
        label10= tk.Label(self, text='')
        label10.grid(row=14, column=5, columnspan=2)
        buttonquit = tk.Button(self, text="Quit", width=20, height = 3, command=close_window)
        buttonquit.grid(row=14, column=7, columnspan=4)
        label10 = tk.Label(self, text='', width=10)
        label10.grid(row=14, column=11, sticky='e')
        #line 2
        label20 = tk.Label(self, text='', height=5)
        label20.grid(row=15, column=0, columnspan=12, sticky="nsew")


def close_window ():
    app.destroy()


if __name__ == "__main__":
    app = MainApp()

    app.overrideredirect(True)
    app.geometry("{0}x{1}+0+0".format(app.winfo_screenwidth(), app.winfo_screenheight()))
    app.focus_set()  # <-- move focus to this widget


    app.mainloop()

Upvotes: 0

Right leg
Right leg

Reputation: 16740

You should use the after method, so as to periodically update the label displaying the time. The following post provides in-depth explanations on how to do so: How to use the after method to make a callback run periodically?

Let's build a minimal example. First off, I need a root, and a label:

import tkinter as tk
root = tk.Tk()
label = tk.Label(root, text="placeholder")
label.pack()

Now, I need a function that will set the current time in the label. As explained in the Q/A I linked to, I need this function to call itself. Since I want the label to be refreshed as fast as possible, I will ask the function to call itself after one millisecond. The time module could be used, but the datetime module wraps the latter so as to provide human-readable time.

import datetime
def set_label():
    currentTime = datetime.datetime.now()
    label['text'] = currentTime
    root.after(1, set_label)

Now I will call the set_label function, in order to start the loop, and then call root.mainloop so as to enter the application's loop:

set_label()
root.mainloop()

All together:

import tkinter as tk
import time

def set_label():
    currentTime = datetime.datetime.now()
    label['text'] = currentTime
    root.after(1, set_label)

root = tk.Tk()
label = tk.Label(root, text="placeholder")
label.pack()

set_label()
root.mainloop()

Upvotes: 8

Related Questions