Swapping frame using canvas in python tkinter - python

I am a newbie in Python, I am keen in being able to swap between different frame in Tkinter. But I can't seems to be able to do it with Canvas. Any expert able to help me point out my mistake?
My main goal is to swap effectively between StartPage and PageOne.
import tkinter as tk
class backbone(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self,*args, **kwargs)
container=tk.Frame(self)
container.config(width=600,height=400,bg="beige")
container.pack()
self.frames={}
for F in (StartPage, PageOne):
frame=F(container,self)
self.frames[F]=frame
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)
canvas = tk.Canvas(self, width = 600, height = 400, bg='#aaaaff')
canvas.pack()
btn_2=tk.Button(self, text="Start Page", bg='#3ab54a',fg='blue',
command=lambda: controller.show_frame(PageOne))
btn_2.place(relx=0.35, rely=0.79, relwidth=0.3, relheight=0.1)
btn_2.pack()
class PageOne(tk.Frame):
def __init__(self,parent,controller):
tk.Canvas.__init__(self,parent)
canvas = tk.Canvas(self, width = 600, height = 400, bg='#aaaaff')
canvas.pack()
btn_1=tk.Button(self, text="PageOne", bg='#3ab54a',fg='blue',
command=lambda: controller.show_frame(StartPage))
btn_1.place(relx=0.35, rely=0.79, relwidth=0.3, relheight=0.1)
btn_1.pack()
app=backbone()
app.mainloop()

Here ya go. You had a bunch of issues. I commented everything in the code that was fixed or changed.
import tkinter as tk
#prepare some data
ButtonPlace = dict(relx=0.35, rely=0.79, relwidth=0.3, relheight=0.1)
ButtonConfig = dict(bg='#3ab54a', fg='blue', activebackground='#3ab54a', activeforeground='blue')
CanvasConfig = dict(width=600, height=400, highlightthickness=0)
#class names should start with a capital letter
class BackBone(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
#you don't need an inner frame so I got rid of it
#init some vars for storing and managing pages
self.page = 0
self.pages = {}
self.page_names = []
#make a refererence of pages and page names
for C in [StartPage, PageOne]:
self.pages[C.NAME]=C(self)
self.page_names.append(C.NAME)
#you can just use one button for every page
self.btn = tk.Button(self, text="Start Page", command=self.next_page, **ButtonConfig)
self.btn.place(**ButtonPlace)
#init start page
self.btn.invoke()
def next_page(self):
#whatever page is packed ~ forget it
for n, f in self.pages.items():
f.pack_forget()
#get page name
name = self.page_names[self.page]
#pack page associated with name
self.pages[name].pack()
#change button text to the name of this page (same as you had it)
self.btn['text'] = name
#raise the button up in z-order
self.btn.tkraise()
#prime next page number
self.page = (self.page + 1) % len(self.page_names)
class StartPage(tk.Canvas):
#static page name reference
NAME = 'Start Page'
#the proper term is master ~ not parent. controller is no more
def __init__(self, master):
tk.Canvas.__init__(self, master, bg='#aaaaff', **CanvasConfig)
#you don't need a frame. make the whole thing a canvas
#apply StartPage comments to this page, as well
class PageOne(tk.Canvas):
NAME = 'Page One'
def __init__(self, master):
tk.Canvas.__init__(self, master, bg='#ffaaaa', **CanvasConfig)
#this is the proper way to initialize your app
if __name__ == '__main__':
app = BackBone()
app.configure(bg='beige', highlightthickness=0, bd=0)
app.resizable(False, False)
app.mainloop()

Related

Why aren't radiobuttons working in a Tkinter window with multiple frames?

I copied Python code to create a Tkinter window with multiple frames. I put many kinds of widgets into it with no problem but when I add radiobuttons, those act funny, although they work fine in a regular window (without multiple pages). Whether I set the value or not, none of the radiobuttons are selected. What's worse, if I just pass the mouse pointer over a radiobutton, it looks like it gets selected although I didn't click it. If I pass the mouse pointer over both radiobuttons, they BOTH look selected, violating the one-of-many-selections rule of radiobuttons.
I should add that I tried this with a pack manager and with a grid manager. The results are the same.
Here's a stripped-down version of my code:
import tkinter as tk
class MainWindow(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# Set the title of the main window.
self.title('Multi-frame window')
# Set the size of the main window to 300x300 pixels.
self.geometry('300x100')
# This container contains all the pages.
container = tk.Frame(self)
container.grid(row=1, column=1)
self.frames = {} # These are pages to which we want to navigate.
# For each page...
for F in (StartPage, PageOne):
# ...create the page...
frame = F(container, self)
# ...store it in a frame...
self.frames[F] = frame
# ..and position the page in the container.
frame.grid(row=0, column=0, sticky='nsew')
# The first page is StartPage.
self.show_frame(StartPage)
def show_frame(self, name):
frame = self.frames[name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text='Start Page')
label.grid(row=1, column=1)
# When the user clicks on this button, call the
# show_frame method to make PageOne appear.
button1 = tk.Button(self, text='Visit Page 1',
command=lambda : controller.show_frame(PageOne))
button1.grid(row=2, column=1)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# When the user clicks on this button, call the
# show_frame method to make StartPage appear.
button1 = tk.Button(self, text='Back to Start',
command=lambda : controller.show_frame(StartPage))
button1.grid(row=1, column=1)
options_label = tk.Label(self, text='Choose an option: ')
options_label.grid(row=2, column=1)
options_value = tk.IntVar()
first_option = tk.Radiobutton( self , text = 'Option 1' ,
variable = options_value , value = 1 )
second_option = tk.Radiobutton( self , text = 'Option 2' ,
variable = options_value , value = 2 )
first_option.grid(row=2, column=2)
second_option.grid(row=2, column=3)
options_value.set(1)
if __name__ == '__main__':
app = MainWindow()
app.mainloop()
The problem is that options_value is a local value that gets destroyed when __init__ finishes.
You need to save a reference to it, such as self.options_value.

Variables from other classes in Tkinter [duplicate]

This is a shortened example of a longer application where I have multiple pages of widgets collecting information input by the user. The MyApp instantiates each page as a class. In the example, PageTwo would like to print the value of the StringVar which stores the data from an Entry widget in PageOne.
How do I do that? Every attempt I've tried ends up with one exception or another.
from tkinter import *
from tkinter import ttk
class MyApp(Tk):
def __init__(self):
Tk.__init__(self)
container = ttk.Frame(self)
container.pack(side="top", fill="both", expand = True)
self.frames = {}
for F in (PageOne, PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky = NSEW)
self.show_frame(PageOne)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class PageOne(ttk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
ttk.Label(self, text='PageOne').grid(padx=(20,20), pady=(20,20))
self.make_widget(controller)
def make_widget(self, controller):
self.some_input = StringVar
self.some_entry = ttk.Entry(self, textvariable=self.some_input, width=8)
self.some_entry.grid()
button1 = ttk.Button(self, text='Next Page',
command=lambda: controller.show_frame(PageTwo))
button1.grid()
class PageTwo(ttk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
ttk.Label(self, text='PageTwo').grid(padx=(20,20), pady=(20,20))
button1 = ttk.Button(self, text='Previous Page',
command=lambda: controller.show_frame(PageOne))
button1.grid()
button2 = ttk.Button(self, text='press to print', command=self.print_it)
button2.grid()
def print_it(self):
print ('The value stored in StartPage some_entry = ')#What do I put here
#to print the value of some_input from PageOne
app = MyApp()
app.title('Multi-Page Test App')
app.mainloop()
Leveraging your controller
Given that you already have the concept of a controller in place (even though you aren't using it), you can use it to communicate between pages. The first step is to save a reference to the controller in each page:
class PageOne(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
...
class PageTwo(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
...
Next, add a method to the controller which will return a page when given the class name or some other identifying attribute. In your case, since your pages don't have any internal name, you can just use the class name:
class MyApp(Tk):
...
def get_page(self, classname):
'''Returns an instance of a page given it's class name as a string'''
for page in self.frames.values():
if str(page.__class__.__name__) == classname:
return page
return None
note: the above implementation is based on the code in the question. The code in the question has it's origin in another answer here on stackoverflow. This code differs from the original code slightly in how it manages the pages in the controller. This uses the class reference as a key, the original answer uses the class name.
With that in place, any page can get a reference to any other page by calling that function. Then, with a reference to the page, you can access the public members of that page:
class PageTwo(ttk.Frame):
...
def print_it(self):
page_one = self.controller.get_page("PageOne")
value = page_one.some_entry.get()
print ('The value stored in StartPage some_entry = %s' % value)
Storing data in the controller
Directly accessing one page from another is not the only solution. The downside is that your pages are tightly coupled. It would be hard to make a change in one page without having to also make a corresponding change in one or more other classes.
If your pages all are designed to work together to define a single set of data, it might be wise to have that data stored in the controller, so that any given page does not need to know the internal design of the other pages. The pages are free to implement the widgets however they want, without worrying about which other pages might access those widgets.
You could, for example, have a dictionary (or database) in the controller, and each page is responsible for updating that dictionary with it's subset of data. Then, at any time you can just ask the controller for the data. In effect, the page is signing a contract, promising to keep it's subset of the global data up to date with what is in the GUI. As long as you maintain the contract, you can do whatever you want in the implementation of the page.
To do that, the controller would create the data structure before creating the pages. Since we're using tkinter, that data structure could be made up of instances of StringVar or any of the other *Var classes. It doesn't have to be, but it's convenient and easy in this simple example:
class MyApp(Tk):
def __init__(self):
...
self.app_data = {"name": StringVar(),
"address": StringVar(),
...
}
Next, you modify each page to reference the controller when creating the widgets:
class PageOne(ttk.Frame):
def __init__(self, parent, controller):
self.controller=controller
...
self.some_entry = ttk.Entry(self,
textvariable=self.controller.app_data["name"], ...)
Finally, you then access the data from the controller rather than from the page. You can throw away get_page, and print the value like this:
def print_it(self):
value = self.controller.app_data["address"].get()
...
I faced a challenge in knowing where to place the print_it function.
i added the following to make it work though I don't really understand why they are used.
def show_frame(self,page_name):
...
frame.update()
frame.event_generate("<<show_frame>>")
and added the show_frame.bind
class PageTwo(tk.Frame):
def __init__(....):
....
self.bind("<<show_frame>>", self.print_it)
...
def print_it(self,event):
...
Without the above additions, when the mainloop is executed,
Page_Two[frame[print_it()]]
the print_it function executes before PageTwo is made Visible.
try:
import tkinter as tk # python3
from tkinter import font as tkfont
except ImportError:
import Tkinter as tk #python2
import tkFont as tkfont
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family="Helvetica", size=18, weight="bold", slant="italic")
# data Dictionary
self.app_data = {"name": tk.StringVar(),
"address": tk.StringVar()}
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others.
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):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
''' Show a frame for the given page name '''
frame = self.frames[page_name]
frame.tkraise()
frame.update()
frame.event_generate("<<show_frame>>")
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="this is the start page", font=self.controller.title_font)
label.pack(side="top", fill="x", pady=10)
# Update the Name value only
self.entry1 = tk.Entry(self,text="Entry", textvariable=self.controller.app_data["name"])
self.entry1.pack()
button1 = tk.Button(self, text="go to page one", command = lambda: self.controller.show_frame("PageOne")).pack()
button2 = tk.Button(self, text="Go to page Two", command = lambda: self.controller.show_frame("PageTwo")).pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=self.controller.title_font)
label.pack(side="top", fill="x", pady=10)
# Update the Address value only
self.entry1 = tk.Entry(self,text="Entry", textvariable=self.controller.app_data["address"])
self.entry1.pack()
button = tk.Button(self, text="Go to the start page", command=lambda: self.controller.show_frame("StartPage"))
button.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
# Bind the print_it() function to this Frame so that when the Frame becomes visible print_it() is called.
self.bind("<<show_frame>>", self.print_it)
label = tk.Label(self, text="This is page 2", font=self.controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: self.controller.show_frame("StartPage"))
button.pack()
def print_it(self,event):
StartPage_value = self.controller.app_data["name"].get()
print(f"The value set from StartPage is {StartPage_value}")
PageOne_value= self.controller.app_data["address"].get()
print(f"The value set from StartPage is {PageOne_value}")
if __name__ == "__main__":
app = SampleApp()
app.mainloop()

Tkinter Return key bind doesn't work due to class structure

I understand how to bind keys when it's just on a simple frame but since I built my app in a different way, I can't seem to figure out how to bind the return key to press the button or run the function that the button is bounded to. I've been searching for a similar question by others on the website but I haven't found one similar to mine.
I've toned down the rest of my code and have it below:
import tkinter as tk
from tkinter import *
class POS(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 (ErrorPage, MainPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column = 0, sticky = "nsew")
self.show_frame(MainPage)
def show_frame(self,cont):
frame = self.frames[cont]
frame.tkraise()
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
frame = tk.Frame(self)
frame.pack(fill = BOTH)
button = Button(frame, text = "OK", command = self.bindHello)
button.pack(pady=5, padx=10)
frame.bind("<Return>", self.bindHello)
self.bind("<Return>", self.bindHello)
def bindHello(self, event=None):
print("HELLO1")
#Yes this doesn't do anything but I need it for the frame container as set before
class ErrorPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
frame = tk.Frame(self)
frame.pack(fill = BOTH)
button = Button(frame, text = "OK", command = self.bindHello)
button.pack(pady=5, padx=10)
frame.bind("<Return>", self.bindHello)
def bindHello(self, event=None):
print("HELLO2")
app = POS()
app.mainloop()
Simple Button bind I had intended to work as is as follows:
from tkinter import *
master = Tk()
def callback(event=None):
print("Hello " + entry.get())
entry = StringVar()
e = Entry(master, textvariable = entry, width = 15)
e.pack()
b = Button(master, text="OK", command = callback)
b.pack()
master.bind("<Return>", callback)
mainloop()
I would just like to have a simple button bind like the one above but I can't seem to find a way for my main program to work. I think it's due to the way I structured my app, but I'm not entirely sure.
On your sample you bind to the window itself. You can do so in the other one as well in a number of ways:
#1 bind to page object's direct parent, which happens to be a Toplevel-like
#self.master.bind('<Return>', self.bindHello)
#2 recursively search page object's parents, and bind when it's a Toplevel-like
#self.winfo_toplevel().bind('<Return>', self.bindHello)
#3 bind to page object's inner frame's parent's parent, which happens to be a Toplevel-like
#frame.master.master.bind('<Return>', self.bindHello)
#4 recursively search page object's inner frame's parents, and bind when it's a Toplevel-like
frame.winfo_toplevel().bind('<Return>', self.bindHello)

Calling a widget from another class to change its properties in tKinter

I have made a function in the main constructor of my tKinter app which updates certain properties of widgets e.g. their text across multiple frames. What I'm trying to do is change widgets in multiple frames at the same time while in a controller frame.
def update_widgets(self, frame_list, widget_name, criteria, output):
for i in frame_list:
i.widget_name.config(criteria=output)
# update_widgets(self, [Main, AnalysisSection], text_label, text, "foo")
# would result in Main.text_label_config(text="foo") and
# AnalysisSection.text_label_config(text="foo") ideally.
However with this code, I'm encountering two problems. Firstly, I'm getting an attribute error stating that both frames don't have the attribute widget_name. Secondly, when I tried to refer to the widget names with the self prefix, both frames say they don't have the attribute self. Is there a way to fix this?
Full program below:
import tkinter as tk
class Root(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.frames = {}
container = tk.Frame(self)
container.pack(side="bottom", expand=True)#fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
for X in (A, B):
frame=X(container, self)
self.frames[X]=frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(A)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
def update_widgets(self, frame_list, widget_name, criteria, output):
for i in frame_list:
frame = self.frames[i]
widget = getattr(frame, widget_name)
widget[criteria] = output
class A(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.text = 'hello'
self.classLabel = tk.Label(self, text="Frame A")
self.classLabel.pack(side=tk.TOP)
# trying to change this widget
self.wordLabel = tk.Label(self, text="None")
self.wordLabel.pack(side=tk.TOP)
self.changeTextLabel = tk.Label(self, text="Change text above across both frames").pack(side=tk.TOP)
self.changeTextEntry = tk.Entry(self, bg='pink')
self.changeTextEntry.pack(side=tk.TOP)
self.changeFrameButton = tk.Button(text="Change to Frame B", command=lambda: self.controller.show_frame(B))
self.changeFrameButton.pack(side=tk.TOP, fill=tk.X)
self.changeTextEntryButton = tk.Button(self, text="ENTER", width=5, command=lambda: self.controller.update_widgets([A, B], 'self.wordLabel', 'text', self.changeTextEntry.get()))
self.changeTextEntryButton.pack(side=tk.TOP, fill=tk.X)
### calling this function outside of the button; this is already
### called within a function in my project.
x = self.controller.update_widgets([A, B], 'wordLabel', 'text', '*initial change*')
class B(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.text = 'hello'
self.classLabel = tk.Label(self, text="Frame B")
self.classLabel.pack(side=tk.TOP)
# trying to change this widget
self.wordLabel = tk.Label(self, text="None")
self.wordLabel.pack(side=tk.TOP)
self.changeTextLabel = tk.Label(self, text="Change text above across both frames").pack(side=tk.TOP)
self.changeTextEntry = tk.Entry(self, bg='light yellow').pack(side=tk.TOP)
self.changeFrameButton = tk.Button(text="Change to Frame A", command=lambda: self.controller.show_frame(A))
self.changeFrameButton.pack(side=tk.TOP, fill=tk.X)
self.changeTextEntryButton = tk.Button(self, text="ENTER", width=5, command=lambda: self.controller.update_widgets([A, B], 'self.wordLabel', 'text', self.changeTextEntry.get()))
self.changeTextEntryButton.pack(side=tk.TOP, fill=tk.X)
if __name__ == '__main__':
app = Root()
The problem in your code is that you're trying to get an attribute of a class rather than an instance of a class. You need to convert i to the actual instance of that class. You have the additional problem that you're passing 'self.wordLabel' rather than just 'wordLabel'.
A simple fix is to look up the instance in self.frames
def update_widgets(self, frame_list, widget_name, criteria, output):
for i in frame_list:
frame = self.frames[i]
label = getattr(frame, widget_name)
label[criteria] = output
You also need to change the button command to look like this:
self.changeTextEntryButton = tk.Button(... command=lambda: self.controller.update_widgets([A,B], 'wordLabel', 'text', self.changeTextEntry.get()))
If you intend for update_widgets to always update all of the page classes, there's no reason to pass the list of frame classes in. Instead, you can just iterate over the known classes:
def update_widgets(self, widget_name, criteria, output):
for frame in self.frames.values():
label = getattr(frame, 'classLabel')
label[criteria] = output
You would then need to modify your buttons to remove the list of frame classes:
self.changeTextEntryButton = tk.Button(..., command=lambda: self.controller.update_widgets('wordLabel', 'text', self.changeTextEntry.get()))

How can I open a new window when the user clicks the button?

How would I create a new window when the user clicks a button (still needs creating)? I have took some code out to make this shorter. I need a button creating and when they hit that button, a new window opens. I haven't created the button because the button has to be linked to the new window. Please help
My imports...
class App:
def __init__(self, master):
self.master = master
# call start to initialize to create the UI elemets
self.start()
def start(self):
self.master.title("E-mail Extranalyser")
self.now = datetime.datetime.now()
tkinter.Label(
self.master, text=label01).grid(row=0, column=0, sticky=tkinter.W)
# CREATE A TEXTBOX
self.filelocation = tkinter.Entry(self.master)
self.filelocation["width"] = 60
self.filelocation.focus_set()
self.filelocation.grid(row=0, column=1)
# CREATE A BUTTON WITH "ASK TO OPEN A FILE"
# see: def browse_file(self)
self.open_file = tkinter.Button(
self.master, text="Browse...", command=self.browse_file)
# put it beside the filelocation textbox
self.open_file.grid(row=0, column=2)
# now for a button
self.submit = tkinter.Button(
self.master, text="Execute!", command=self.start_processing,
fg="red")
self.submit.grid(row=13, column=1, sticky=tkinter.W)
def start_processing(self):
#code here
def browse_file(self):
# put the result in self.filename
self.filename = filedialog.askopenfilename(title="Open a file...")
# this will set the text of the self.filelocation
self.filelocation.insert(0, self.filename)
root = tkinter.Tk()
app = App(root)
root.mainloop()
Use a Toplevel to open a new one. Modify your code as shown below.
self.NewWindow = tkinter.Button(self.master,
text="New Window",
command=self.CreateNewWindow)
def CreateNewWindow(self):
self.top = tkinter.Toplevel()
self.top.title("title")
Take a look at https://www.youtube.com/watch?v=jBUpjijYtCk. Working through this tutorial would probably help you but this specific video shows how to work with multiple pages.
Something like this:
from tkinter import *
class Sample(Tk):
def __init__(self,*args, **kwargs):
Tk.__init__(self, *args, **kwargs)
container = Frame(self)
container.pack(side="top", fill="both", expand = True)
self.frames = {}
for F in (MainPage, OtherPage):
frame=F(container, self)
self.frames[F]=frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(MainPage)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
class MainPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
Label(self, text="Start Page").pack()
Button(self, text="other page?", command=lambda:controller.show_frame(OtherPage)).pack()
class OtherPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
Label(self, text="Next Page").pack()
Button(self, text="back", command=lambda:controller.show_frame(MainPage)).pack()
app = Sample()
app.mainloop()

Categories

Resources