Related
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()
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()
I have this code to change the title of the frame. I have two pages here. In PageOne class, we get the title and by pressing the button, the title changes. And, we can use the Go to page two button to navigate to PageTwo. here also we can do the same.
Here is my question, how I can define only one function instead of using function add1() in PageOne, and function add2() in PageTwo. I mean I only define one function on PageOne and use the same function in PageTwo, and show the results in the frame2.
import tkinter as tk
class Data:
def __init__(self):
self.number1 = tk.StringVar()
self.number2 = tk.StringVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.minsize(700, 700)
container = tk.Frame(self)
container.pack()
self.data = Data()
self.frames = {}
for F in (PageOne, PageTwo):
frame = F(container, self.data)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.frames[PageOne].page_button.config(command=self.go_to_page_two)
self.show_frame(PageOne)
def go_to_page_two(self):
self.show_frame(PageTwo)
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class PageOne(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
entry1 = tk.Entry(self, textvariable=self.data.number1)
entry1.pack()
self.button1 = tk.Button(self, text="click", command=self.add1)
self.button1.pack()
self.frame1 = tk.LabelFrame(self, height=200, width=200, borderwidth=2)
self.frame1.pack()
self.page_button = tk.Button(self, text="Go to Page Two")
self.page_button.pack()
def add1(self):
self.frame1.config(text=str(self.data.number1.get()))
class PageTwo(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
entry2 = tk.Entry(self, textvariable=self.data.number2)
entry2.pack()
self.button2 = tk.Button(self, text="click", command=self.add2)
self.button2.pack()
self.frame2 = tk.LabelFrame(self, height=200, width=200, borderwidth=2)
self.frame2.pack()
def add2(self):
self.frame2.config(text=str(self.data.number2.get()))
app = SampleApp()
app.mainloop()
you can do in this way:
import tkinter as tk
class Data:
def __init__(self):
self.number = tk.StringVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.minsize(700, 700)
container = tk.Frame(self)
container.pack()
self.data = Data()
self.frames = {}
for F in (PageOne,):
frame = F(container, self.data)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class PageOne(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
entry1 = tk.Entry(self, textvariable=self.data.number)
entry1.pack()
self.button1 = tk.Button(self, text="click", command=lambda : self.add(self.frame1, data.number))
self.button1.pack()
self.frame1 = tk.LabelFrame(self, height=200, width=200, borderwidth=2)
self.frame1.pack()
self.button2 = tk.Button(self, text="click", command=lambda : self.add(self.frame2, data.number))
self.button2.pack()
self.frame2 = tk.LabelFrame(self, height=200, width=200, borderwidth=2)
self.frame2.pack()
def add(self, frame, data):
frame.config(text=str(self.data.number.get()))
app = SampleApp()
app.mainloop()
I'm trying to load a new frame when the user presses the login button as long as the details entered are correct. I've included print commands within the LogInCheck function in order to see if the code is executing correctly, which it is. My only problem is that it wont change the frame. I get the error 'LogIn' object missing attribute 'show_frame'
from tkinter import *
from tkinter import ttk
import tkinter as tk
LARGE_FONT= ("Arial", 16)
SMALL_FONT= ("Arial", 12)
current_tariff = None
def tariff_A():
global current_tariff
current_tariff= "A"
def tariff_B():
global current_tariff
current_tariff= "B"
def tariff_C():
global current_tariff
current_tariff= "C"
class PhoneCompany(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 (StartPage, PageOne, PageTwo, PageThree, PageFour, PageFive, LogIn):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(LogIn)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
Thats my main class and this is the login page class:
class LogIn(tk.Frame):
def LogInCheck(self):
global actEntry
global pinEntry
act = "james"
pin = "Python123"
actNum = actEntry.get()
pinNum = pinEntry.get()
print("FUNCTION RUN")
if actNum == act and pinNum == pin:
print("CORRECT")
self.show_frame(StartPage)
elif actNum != act or pinNum != pin:
print("INCORRECT")
self.show_frame(LogIn)
def __init__(self, parent, controller):
global actEntry
global pinEntry
self.controller = controller
tk.Frame.__init__(self, parent)
logLabel = ttk.Label(self, text = "Login With Your Username and
Password", font = LARGE_FONT)
logLabel.pack(side = TOP, anchor = N, expand = YES)
actLabel = Label(self, text = 'Username:')
actEntry = Entry(self)
pinLabel = Label(self, text = 'Password: ')
pinEntry = Entry(self, show ="*")
actLabel.pack(pady =10, padx = 10, side = TOP, anchor = N)
pinLabel.pack(pady =5, padx = 10, side = TOP, anchor = S)
actEntry.pack(pady =10, padx = 10, side = TOP, anchor = N)
pinEntry.pack(pady =5, padx = 10, side = TOP, anchor = S)
logInButton = tk.Button(self, text = "Login",
command = self.LogInCheck)
logInButton.pack(side = TOP, anchor = S)
quitButton = tk.Button(self, text = "Quit", command = quit)
quitButton.pack(side = BOTTOM, anchor = S)
if __name__ == "__main__":
app = PhoneCompany()
app.mainloop()
I'll include my full code if you need to look at the rest of it:
from tkinter import *
from tkinter import ttk
import tkinter as tk
LARGE_FONT= ("Arial", 16)
SMALL_FONT= ("Arial", 12)
current_tariff = None
def tariff_A():
global current_tariff
current_tariff= "A"
def tariff_B():
global current_tariff
current_tariff= "B"
def tariff_C():
global current_tariff
current_tariff= "C"
class PhoneCompany(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 (StartPage, PageOne, PageTwo, PageThree, PageFour, PageFive, LogIn):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(LogIn)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="MENU", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button = tk.Button(self, text="View Account Balance",
command=lambda: controller.show_frame(PageOne))
button.pack()
button2 = tk.Button(self, text="Display Current Tariff",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
button3 = tk.Button(self, text="View List of Rates",
command=lambda: controller.show_frame(PageThree))
button3.pack()
button4 = tk.Button(self, text="View Latest Bill",
command=lambda: controller.show_frame(PageFour))
button4.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Account Balance", font=LARGE_FONT)
label.pack(pady=10,padx=10)
sublabel = tk.Label(self, text="Your current account balance is £230", font=SMALL_FONT)
sublabel.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Menu",
command=lambda: controller.show_frame(StartPage))
button1.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
global current_tariff
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Current Tariff", font=LARGE_FONT)
label.pack(pady=10,padx=10)
sublabel = tk.Label(self, text="Your current tariff is "+str(current_tariff), font=SMALL_FONT)
sublabel.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Change Tariff",
command=lambda: controller.show_frame(PageFive))
button1.pack()
button2 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button2.pack()
class PageThree(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Tariff Rates", font=LARGE_FONT)
label.pack(pady=10,padx=10)
sublabel = tk.Label(self, text="Peak Rates: A: £0.30 | B: £0.10 | C: £0.90", anchor="w", font=SMALL_FONT)
sublabel.pack(pady=10,padx=10)
sublabel2 = tk.Label(self, text="Off Peak: A: £0.05 | B: £0.02 | C: -", anchor="w", font=SMALL_FONT)
sublabel2.pack(pady=10,padx=10)
sublabel3 = tk.Label(self, text="Line Rental: A: £15.00 | B: £20.00 | C: £30.00", anchor="w", font=SMALL_FONT)
sublabel3.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
class PageFour(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Latest Bill", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
class PageFive(tk.Frame):
def __init__(self, parent, controller):
global current_tariff
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Change Tariff", font=LARGE_FONT)
label.pack(pady=10,padx=10)
sublabel = tk.Label(self, text="Select new tariff\nView list of tariff rates on the main menu to see the prices.", font=SMALL_FONT)
sublabel.pack(pady=10,padx=10)
button1 = tk.Button(self, text="A",
command=lambda:[controller.show_frame(StartPage),tariff_A])
button1.pack()
button2 = tk.Button(self, text="B",
command=lambda:[controller.show_frame(StartPage),tariff_B])
button2.pack()
button3 = tk.Button(self, text="C",
command=lambda:[controller.show_frame(StartPage),tariff_C])
button3.pack()
button4 = tk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button4.pack()
class LogIn(tk.Frame):
def LogInCheck(self):
global actEntry
global pinEntry
act = "james"
pin = "Python123"
actNum = actEntry.get()
pinNum = pinEntry.get()
print("FUNCTION RUN")
if actNum == act and pinNum == pin:
print("CORRECT")
self.show_frame(StartPage)
elif actNum != act or pinNum != pin:
print("INCORRECT")
self.show_frame(LogIn)
def __init__(self, parent, controller):
global actEntry
global pinEntry
self.controller = controller
tk.Frame.__init__(self, parent)
logLabel = ttk.Label(self, text = "Login With Your Username and Password", font = LARGE_FONT)
logLabel.pack(side = TOP, anchor = N, expand = YES)
actLabel = Label(self, text = 'Username:')
actEntry = Entry(self)
pinLabel = Label(self, text = 'Password: ')
pinEntry = Entry(self, show ="*")
actLabel.pack(pady =10, padx = 10, side = TOP, anchor = N)
pinLabel.pack(pady =5, padx = 10, side = TOP, anchor = S)
actEntry.pack(pady =10, padx = 10, side = TOP, anchor = N)
pinEntry.pack(pady =5, padx = 10, side = TOP, anchor = S)
# runs the 'LoginCheck' function
logInButton = tk.Button(self, text = "Login",
command = self.LogInCheck)
logInButton.pack(side = TOP, anchor = S)
quitButton = tk.Button(self, text = "Quit", command = quit)
quitButton.pack(side = BOTTOM, anchor = S)
if __name__ == "__main__":
app = PhoneCompany()
app.mainloop()
I know it's quite messy and there may be other errors, but for now i just need to figure out why it wont change the frame after successfully logging in.
It needs to be self.controller.show_frame(StartPage).
I'm attempting to write a program in tkinter where the user clicks on a button with their name and a verification page shows it to them. The problem I'm having is that the variable is either resetting or I'm accessing it wrong:
import tkinter as tk
from tkinter import *
from tkinter import ttk
LARGE_FONT = ("Times New Roman", 12)
NORM_FONT = ("Times New Roman", 10)
root = Tk()
root.withdraw()
class DIS(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.iconbitmap(self, default="")
tk.Tk.wm_title(self, "program")
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 (StartPage, contactQues, nameVerify):
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):
tk.Frame.__init__(self, parent)
button2 = ttk.Button(self, text = "Name Select",
command=lambda: controller.show_frame(contactQues))
button2.pack()
class contactQues(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
global name
name = StringVar()
label1 = tk.Label(self, text = "Select Your Name", font = LARGE_FONT)
label1.pack(pady=10, padx=10)
button2 = ttk.Button(self, text = "Bojangles", command = self.bojangles)
button2.pack(pady=5)
def bojangles(self):
name.set("Mr. Bojangles")
self.controller.show_frame(nameVerify)
#
#Many other names to select
#
class nameVerify(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
namename = name.get()
label5 = tk.Label(self, text = "Your Name:", font = LARGE_FONT)
label5.pack(pady=10, padx=10)
labelcontact = tk.Label(self, text = namename, font = NORM_FONT)
labelcontact.pack()
app = DIS()
app.mainloop()
So, in essence, what I want to happen is:
- Program runs and user presses "Name select", user selects their name, and the final page shows their selection.
I've tried messing with globals, textvariables for the labelcontact label, StringVar(), etc. and can't seem to peg this one down.
Is there a better way to do this? Or am I doing something inherently wrong?
Thank you for any help.
I suggest making name an attribute of the DIS class. Then your StartPage and nameVerify instances can access it via their controller attributes. If you want labelcontact to update automatically whenever name does, use the textvariable attribute.
Additionally, you need to delete your root = Tk() and root.withdraw() lines. I don't know why, but as long as they're there, the labelcontact Label won't properly update. They don't appear to do anything in any case - hopefully they aren't crucial to your actual code.
import tkinter as tk
from tkinter import *
from tkinter import ttk
LARGE_FONT = ("Times New Roman", 12)
NORM_FONT = ("Times New Roman", 10)
class DIS(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.iconbitmap(self, default="")
tk.Tk.wm_title(self, "program")
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.name = StringVar()
self.frames = {}
for F in (StartPage, contactQues, nameVerify):
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):
tk.Frame.__init__(self, parent)
button2 = ttk.Button(self, text = "Name Select",
command=lambda: controller.show_frame(contactQues))
button2.pack()
class contactQues(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text = "Select Your Name", font = LARGE_FONT)
label1.pack(pady=10, padx=10)
button2 = ttk.Button(self, text = "Bojangles", command = self.bojangles)
button2.pack(pady=5)
def bojangles(self):
self.controller.name.set("Mr. Bojangles")
self.controller.show_frame(nameVerify)
#
#Many other names to select
#
class nameVerify(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label5 = tk.Label(self, text = "Your Name:", font = LARGE_FONT)
label5.pack(pady=10, padx=10)
labelcontact = tk.Label(self, textvariable = self.controller.name, font = NORM_FONT)
labelcontact.pack()
app = DIS()
app.mainloop()
I am writing a GUI code that opens frame using Tkinter. I referred various websites. Now while testing I am facing problem. For example:
In 1st frame, I select MainController button.
in 2nd frame press MC_CONFIG button.
in 3rd frame I set XML PATH then clicked MC SYSTEM.xml button
If I go to Back to Home button and follow the same procedure, MC_CONFIG button gets disabled (i.e I cannot go further).
If I comment(delete) this line(126)
tk.Frame.__init__(self)
in method def nacxml(self): of class MC_CONFIG, it is working perfectly.
The below one is just part of my main code bu facing problem here.
Please guide me.
import Tkinter as tk
import xml.dom.minidom
from Tkinter import *
import tkMessageBox
from array import *
import tkFileDialog
import os
LARGE_FONT= ("Verdana", 12)
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Switch Installer window")
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 (StartPage, PageOne, PageTwo):
for F in (StartPage, MainController,xmlpath,MC_CONFIG):
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):
tk.Frame.__init__(self, parent)
self.modules_label = ['MAINCONTROLLER']
self.modules_function = [MainController]
self.modules_label_index = len(self.modules_label)
self.modules_function_index = len(self.modules_function)
print("self.modules_label_index = %s" %self.modules_label_index)
label = Label(self, text="SWITCH INSTALLER", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#button = Button(self, text="Visit Page 1",
button3 = Button(self, text="SELECT",
command=lambda: controller.show_frame(MainController))
button3.pack()
label3 = Label(self, text="MainController", font = LARGE_FONT)
label3.place(x= 50, y=100+10)
button8 = Button(self, text="Quit", command=self.quit)
button8.pack()
class xmlpath(tk.Frame):
#xfilename="+++"
def __init__(self, parent, controller):
self.xfilename="srinivasan"
tk.Frame.__init__(self, parent)
label = Label(self, text="Page One!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
button1 = Button(self, text="XML PATH",
command=self.newxmlpath)
button1.pack()
def newxmlpath(self,*args):
# ObjNAC= NacHandler()
self.filename = tkFileDialog.askopenfilename()
print(self.filename)
#ObjNAC.temp_method(self,self.filename)
return self.filename
class MainController(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = Label(self, text="|--Frame1 MainController --|", font = LARGE_FONT)
label.pack(pady=10,padx=10)
mc_button1 = Button(self, text="MC_CONFIG", command = lambda: controller.show_frame(MC_CONFIG))
mc_button1.pack()
mc_button2 = Button(self, text="MENU HOME", command = lambda: controller.show_frame(StartPage))
mc_button2.pack()
self.pack (fill = BOTH, expand = 1)
class MC_CONFIG(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
print "Inside MC_CONFIG"
self.database = []
# set root as parent
self.parent = parent
label1 = Label(self, text="|------------Frame2--MainController---------------|", font=LARGE_FONT)
label1.pack(pady = 10,padx = 10)
label2 = Label(self, text="Edit SYSTEM.xml File", font=LARGE_FONT)
label2.pack(pady = 10,padx = 10)
button1 = Button(self, text="XML PATH",
command=self.newxmlpath)
button1.pack(pady = 10,padx = 10)
button2 = Button(self, text = "MC SYSTEM.xml", command = self.nacxml)
button2.pack(pady = 10,padx = 10)
button3 = Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button3.pack(pady = 10,padx = 10)
def newxmlpath(self, *args):
self.filename = tkFileDialog.askopenfilename()
print(self.filename)
return self.filename
def nacxml(self):
tk.Frame.__init__(self)
print "===Inside Nacxml1==="
app = SeaofBTCapp()
app.geometry ("640x480+300+300")
app.mainloop()
The problem is this:
def nacxml(self):
tk.Frame.__init__(self)
You should only ever call the superclass constructor from within the constructor of the subclass. Doing so anywhere else will certainly not do whatever you think it's doing.
Finally code is working as intended
1.Deleted tk.Frame.__init__(self) as indicated by Bryan Oakley
def nacxml(self):
tk.Frame.__init__(self)
2.Controller is not intialized in self.But it is present in def __init__(self, parent, controller):.Hence added
self.controller = controller in MC_CONFIG class
class MC_CONFIG(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
print "Inside MC_CONFIG"
So can be used in below method as self.controller.show_frame(StartPage)
def nacxml(self):
tk.Frame.__init__(self)
print "===Inside Nacxml1==="
# xml read,edit,widget code will be added here
self.controller.show_frame(StartPage)