This Tkinter app displays the same label across 3 frames, but is only updated on Frame3. why is Frame3 the active one when I start the app?
import tkinter as tk
from tkinter import ttk
import time
class RootContent(tk.Frame):
"""
Define content of main window.
"""
def __init__(self, parent):
super(RootContent, self).__init__(parent)
"""
The application is divided in pages, each page is a Frame(). The script starts by default 'raising' the page1.
When click to change page, you call the raise_frame(frame_number) function to display a new page.
"""
# all pages
page1=tk.Frame()
page2=tk.Frame()
page3=tk.Frame()
tk.Label(page1, text='PAGE 1', font='Verdana 20 bold').pack()
tk.Label(page2, text='PAGE 2', font='Verdana 20 bold').pack()
tk.Label(page3, text='PAGE 3', font='Verdana 20 bold').pack()
# button page 1
tk.Button(page1, text='page 2', command=lambda: raise_frame(page2)).pack(side='right')
tk.Button(page1, text='page 3', command=lambda: raise_frame(page3)).pack(side='left')
# buttons page 2
tk.Button(page2, text='page 1', command=lambda: raise_frame(page1)).pack(side='left')
tk.Button(page2, text='page 3', command=lambda: raise_frame(page3)).pack(side='right')
# buttons page 3
tk.Button(page3, text='page 2', command=lambda: raise_frame(page2)).pack(side='left')
tk.Button(page3, text='page 1', command=lambda: raise_frame(page1)).pack(side='right')
# function to update time being displayed
def update_timelabel():
time_actual = time.asctime()
# timelabel.config(text=time_actual)
timelabel['text']=time_actual
timelabel.after(1000, update_timelabel)
# function to change screen
def raise_frame(frame):
frame.tkraise()
# define layout for all page frames inside root
for frame in (page1, page2, page3):
# horizontal line
ttk.Separator(frame, orient='horizontal').pack(fill='x', anchor='s')
# time label
timelabel = tk.Label(frame, text='time info') # text to be modified
timelabel.pack()
# place frames in root
frame.grid(row=0, column=0, sticky='news')
# update time
update_timelabel()
# show page 1
raise_frame(page1)
# call main loop
if __name__ == '__main__':
# main window
root = tk.Tk()
root.resizable(0,0)
root.geometry('400x200')
main = RootContent(root)
root.mainloop()
Is it a good idea to display a 'global label' that I only need to specify one time for as many frames as I have?
The original loop (for frames in (ALL 3 FRAMES): was made to expand the frame across the root window.
for frame in (page1, page2, page3):
frame.grid(row=0, column=0, sticky='news')
And I used to add a widgets that will appear on all frames.
CodePudding user response:
The reason why it only works for frame 3 is because you reassigned the timelabel
3 times. The last time the timelabel
updates its master is the last loop when it does something like this: tk.Label(page3, text='time info')
. So how can you expect the timelabel
works for all the frames? So I came up with a solution where timelabel
is "kind of" stored 3 times. Basically you pass the timelabel
you created as a parameter to the update_timelabel()
function. This code below works for what you have asked:
import tkinter as tk
from tkinter import ttk
import time
class RootContent(tk.Frame):
"""
Define content of main window.
"""
def __init__(self, parent):
super(RootContent, self).__init__(parent)
"""
The application is divided in pages, each page is a Frame(). The script starts by default 'raising' the page1.
When click to change page, you call the raise_frame(frame_number) function to display a new page.
"""
# all pages
page1=tk.Frame()
page2=tk.Frame()
page3=tk.Frame()
tk.Label(page1, text='PAGE 1', font='Verdana 20 bold').pack()
tk.Label(page2, text='PAGE 2', font='Verdana 20 bold').pack()
tk.Label(page3, text='PAGE 3', font='Verdana 20 bold').pack()
# button page 1
tk.Button(page1, text='page 2', command=lambda: raise_frame(page2)).pack(side='right')
tk.Button(page1, text='page 3', command=lambda: raise_frame(page3)).pack(side='left')
# buttons page 2
tk.Button(page2, text='page 1', command=lambda: raise_frame(page1)).pack(side='left')
tk.Button(page2, text='page 3', command=lambda: raise_frame(page3)).pack(side='right')
# buttons page 3
tk.Button(page3, text='page 2', command=lambda: raise_frame(page2)).pack(side='left')
tk.Button(page3, text='page 1', command=lambda: raise_frame(page1)).pack(side='right')
# function to update time being displayed
def update_timelabel(timelabel: tk.Label):
time_actual = time.asctime()
# timelabel.config(text=time_actual)
timelabel['text']=time_actual
timelabel.after(1000, lambda: update_timelabel(timelabel))
# function to change screen
def raise_frame(frame):
frame.tkraise()
# define layout for all page frames inside root
for frame in (page1, page2, page3):
# horizontal line
ttk.Separator(frame, orient='horizontal').pack(fill='x', anchor='s')
# time label
timelabel = tk.Label(frame, text='time info') # text to be modified
timelabel.pack()
# place frames in root
frame.grid(row=0, column=0, sticky='news')
# update time
update_timelabel(timelabel) # passing the label here as a parameter
# show page 1
raise_frame(page1)
# call main loop
if __name__ == '__main__':
# main window
root = tk.Tk()
root.resizable(0,0)
root.geometry('400x200')
main = RootContent(root)
root.mainloop()