Good day StackOverFlow!
I need to update var in next frame, using tkinter after it's was changed. It's work, if i put code on "Page2" in function. BUT.
Can somebody advice please about this?
p.s. I apologize for the code not being clean enough.
import tkinter as tk
from tkinter import ttk
from tkinter import *
#Main frame
class tkinterApp(tk.Tk):
# __init__ function for class tkinterApp
def __init__(self, *args, **kwargs):
# __init__ function for class Tk
tk.Tk.__init__(self, *args, **kwargs)
# creating a container
container = tk.Frame(self)
self.geometry("450x350")
self.title('tool')
container.pack(side = "top", fill = "both", expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
# initializing frames to an empty array
self.frames = {}
# iterating through a tuple consisting
# of the different page layouts
for F in (StartPage,
Page2,):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky ="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
#class
class Pages:
global timeStamp
timeStamp = 0
#start page
class StartPage(tk.Frame, Pages):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
def TimeFocusIn(event):
timeStampInput.delete(0,"end")
timeInputName = ttk.Label(self,
text = "Enter Time in HHMMSS format:")
timeStampInput = ttk.Entry(self)
timeStampInput.insert(0, "HHMMSS")
timeStampInput.bind("<FocusIn>", TimeFocusIn)
#Save time button
def SaveTime(**kwargs):
global timeStamp
var = StringVar()
timeVarOut = timeStampInput.get()
var.set(timeVarOut)
timeVarOutTxt = ttk.Label(self, text=f'{timeVarOut}')
timeVarOutTxt.grid(row = 7, column = 4, padx = 10, pady = 10)
timeStamp = timeVarOut
saveTimeInputButt = ttk.Button(self,
text = "Save time", command = SaveTime)
timeVarText = ttk.Label(self,
text = "TimeStamp is:")
buttPage2 = ttk.Button(self, text ="Next page",
command = lambda : controller.show_frame(Page2))
#Grid placing
timeInputName.grid(row = 5, column = 1, padx = 10, pady = 10, sticky ="nsew")
timeStampInput.grid(row = 5, column = 2, padx = 10, pady = 10, sticky ="nsew")
saveTimeInputButt.grid(row = 5, column = 4, padx = 10, pady = 10, sticky ="nsew")
buttPage2.grid(row = 6, column = 1, padx = 10, pady = 10)
timeVarText.grid(row = 7, column = 2, padx = 10, pady = 10)
#Page 2
class Page2(tk.Frame, Pages):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Next page")
label.grid(row = 0, column = 4, padx = 10, pady = 10)
timeVarOutTxt = ttk.Label(self, text=f'Timestamp is: {timeStamp}')
timeVarOutTxt.grid(row = 1, column = 2, padx = 10, pady = 10)
button1 = ttk.Button(self, text ="Back",
command = lambda : controller.show_frame(StartPage))
button1.grid(row = 1, column = 1, padx = 10, pady = 10)
# Run GUI
app = tkinterApp()
def message():
app.update()
print(timeStamp)
app.after(20, message)
app.after(20, message)
app.mainloop()
CodePudding user response:
If you want to share data between Frames then you could keep it in tkinterApp
as self.timeStamp
and then every page will have access using controller.timeStamp
if you want to access it in some function then keep self.controller = controller
But this can't change text in label - you have to do it on your own using
You have to use self.
in self.timeVarOutTxt
and later in saveTime
you can access label in other frame and change it.
self.controller.frames[Page2].timeVarOutTxt['text'] = f'Timestamp is: {self.controller.timeStamp}'
Working code with other changes:
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import ttk
# --- classes --- # PEP8: all classes after imports
# Main frame # PEP8: one space after `#`
class tkinterApp(tk.Tk):
# __init__ function for class tkinterApp
def __init__(self, *args, **kwargs):
# __init__ function for class Tk
super().__init__(*args, **kwargs)
#self.geometry("450x350")
self.title('tool')
self.time_stamp = 0
# creating a container
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True) # PEP8: inside `()` uses `=` without spaces
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
# initializing frames to an empty array
self.frames = {}
# iterating through a tuple consisting
# of the different page layouts
for F in (StartPage, Page2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
time_input_name = ttk.Label(self, text="Enter Time in HHMMSS format:")
self.time_stamp_input = ttk.Entry(self)
self.time_stamp_input.insert(0, "HHMMSS")
self.time_stamp_input.bind("<FocusIn>", self.time_focus_in)
save_time_input_button = ttk.Button(self, text="Save time", command=self.save_time)
time_var_text = ttk.Label(self, text="TimeStamp is:")
button_page2 = ttk.Button(self, text="Next page", command=lambda:controller.show_frame(Page2))
time_input_name.grid(row=5, column=1, padx=10, pady=10, sticky="nsew")
self.time_stamp_input.grid(row=5, column=2, padx=10, pady=10, sticky="nsew")
save_time_input_button.grid(row=5, column=4, padx=10, pady=10, sticky="nsew")
button_page2.grid(row=6, column=1, padx=10, pady=10)
time_var_text.grid(row=7, column=2, padx=10, pady=10)
def time_focus_in(self, event): # PEP8: `lower_case_names` for functions
self.time_stamp_input.delete(0, "end")
def save_time(self, **kwargs): # PEP8: `lower_case_names` for functions
self.time_var_out_txt = ttk.Label(self, text=self.time_stamp_input.get())
self.time_var_out_txt.grid(row=7, column=4, padx=10, pady=10)
self.controller.time_stamp = self.time_stamp_input.get()
self.controller.frames[Page2].time_var_out_txt['text'] = f'Timestamp is: {self.controller.time_stamp}'
class Page2(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
label = ttk.Label(self, text="Next page")
label.grid(row=0, column=4, padx=10, pady=10)
self.time_var_out_txt = ttk.Label(self, text=f'Timestamp is: {controller.time_stamp}')
self.time_var_out_txt.grid(row=1, column=2, padx=10, pady=10)
button1 = ttk.Button(self, text="Back", command=lambda:controller.show_frame(StartPage))
button1.grid(row=1, column=1, padx=10, pady=10)
# --- functions --- # PEP8: all functions after classes (before main code)
def message():
#app.update() # no need it
print(app.time_stamp, end='\r') # print in the same line
app.after(20, message)
# --- main ---
# Run GUI
app = tkinterApp()
app.after(20, message)
app.mainloop()
PEP 8 -- Style Guide for Python Code
EDIT:
Other idea: in every Page add function before_switch()
and execute it
def show_frame(self, cont):
frame = self.frames[cont]
frame.before_switch()
frame.tkraise()
and this function in class Page2
could update label always before displaying Page2
import tkinter as tk # PEP8: `import *` is not preferred
from tkinter import ttk
# --- classes ---
# Main frame # PEP8: one space after `#`
class tkinterApp(tk.Tk):
# __init__ function for class tkinterApp
def __init__(self, *args, **kwargs):
# __init__ function for class Tk
super().__init__(*args, **kwargs)
#self.geometry("450x350")
self.title('tool')
self.time_stamp = 0
# creating a container
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True) # PEP8: inside `()` uses `=` without spaces
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
# initializing frames to an empty array
self.frames = {}
# iterating through a tuple consisting
# of the different page layouts
for F in (StartPage, Page2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.frame = None
self.show_frame(StartPage)
def show_frame(self, cont):
if self.frame:
self.frame.after()
self.frame = self.frames[cont]
self.frame.before()
self.frame.tkraise()
class Page(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
def before(self):
"""Run before showing Page."""
pass
def after(self):
"""Run after showing Page."""
pass
class StartPage(Page):
def __init__(self, parent, controller):
super().__init__(parent, controller)
time_input_name = ttk.Label(self, text="Enter Time in HHMMSS format:")
self.time_stamp_input = ttk.Entry(self)
self.time_stamp_input.insert(0, "HHMMSS")
self.time_stamp_input.bind("<FocusIn>", self.time_focus_in)
save_time_input_button = ttk.Button(self, text="Save time", command=self.save_time)
time_var_text = ttk.Label(self, text="TimeStamp is:")
button_page2 = ttk.Button(self, text="Next page", command=lambda:controller.show_frame(Page2))
time_input_name.grid(row=5, column=1, padx=10, pady=10, sticky="nsew")
self.time_stamp_input.grid(row=5, column=2, padx=10, pady=10, sticky="nsew")
save_time_input_button.grid(row=5, column=4, padx=10, pady=10, sticky="nsew")
button_page2.grid(row=6, column=1, padx=10, pady=10)
time_var_text.grid(row=7, column=2, padx=10, pady=10)
def time_focus_in(self, event): # PEP8: `lower_case_names` for functions
self.time_stamp_input.delete(0, "end")
def save_time(self, **kwargs): # PEP8: `lower_case_names` for functions
self.time_var_out_txt = ttk.Label(self, text=self.time_stamp_input.get())
self.time_var_out_txt.grid(row=7, column=4, padx=10, pady=10)
def after(self):
"""Update shared value after showing Page."""
self.controller.time_stamp = self.time_stamp_input.get()
class Page2(Page):
def __init__(self, parent, controller):
super().__init__(parent, controller)
label = ttk.Label(self, text="Next page")
label.grid(row=0, column=4, padx=10, pady=10)
self.time_var_out_txt = ttk.Label(self, text=f'Timestamp is: {controller.time_stamp}')
self.time_var_out_txt.grid(row=1, column=2, padx=10, pady=10)
button1 = ttk.Button(self, text="Back", command=lambda:controller.show_frame(StartPage))
button1.grid(row=1, column=1, padx=10, pady=10)
def before(self):
"""Update label before showing Page."""
self.time_var_out_txt['text'] = f'Timestamp is: {self.controller.time_stamp}'
# --- functions ---
def message():
#app.update() # no need it
print(app.time_stamp, end='\r')
app.after(20, message)
# --- main ---
# Run GUI
app = tkinterApp()
app.after(20, message)
app.mainloop()