Tkinter - Go back and forth between frames using buttons

I need functions, preferably one function that can move between pages by pressing the next and back buttons. I assume that this can be done by assigning logical variables to the back and next buttons (not sure if this can be done) to find out if you are going backward or writing off an ordered list of all pages. The index of the currently raised frame must be known. Indexes can be used to determine the next page, and then they will be raised. If the current index is 0 or the last index (in this case 2), and you click back or then respectively, then you will go to the starting class frame, in this case BlankPage.

import tkinter as tk from tkinter import ttk class Program(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) tk.Tk.iconbitmap(self, default = "") tk.Tk.wm_title(self, "") 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 (Add, BlankPage): frame = F(container, self) self.frames[F] = frame frame.grid(row = 0, column = 0, sticky = "nsew") self.show_frame(Add) def show_frame(self,cont): frame = self.frames[cont] frame.tkraise() class Add(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) innerFrame = tk.Frame(self) innerFrame.place(relx=.5, rely=.5, anchor="c", relwidth=1.0, relheight=1.0) innerFrame.grid_rowconfigure(1, weight=1) innerFrame.grid_columnconfigure(0, weight=1) name = tk.Label(innerFrame, text = "User") name.grid(row=0, sticky="NE") pagename = tk.Label(innerFrame, text = "Label") pagename.grid(row=0, sticky="N") next = ttk.Button(innerFrame, text = "Next", command = self.changePage) next.grid(row=2, sticky="E") back = ttk.Button(innerFrame, text = "Back", command = self.changePage) back.grid(row=2, sticky="W") ########################################################################################################### self.pageThree = tk.Frame(innerFrame) self.pageThree.grid(row=1) self.pageThree.grid_rowconfigure(0, weight=1) self.pageThree.grid_columnconfigure(0, weight=1) pagename = tk.Label(self.pageThree, text = "Page 3") pagename.grid(row=0, sticky="N") ########################################################################################################### self.pageTwo = tk.Frame(innerFrame) self.pageTwo.grid(row=1) self.pageTwo.grid_rowconfigure(0, weight=1) self.pageTwo.grid_columnconfigure(0, weight=1) pagename = tk.Label(self.pageTwo, text = "Page 2") pagename.grid(row=0, sticky="N") ########################################################################################################### self.pageOne = tk.Frame(innerFrame) self.pageOne.grid(row=1) self.pageOne.grid_rowconfigure(0, weight=1) self.pageOne.grid_columnconfigure(0, weight=1) pagename = tk.Label(self.pageOne, text = "Page 1") pagename.grid(row=0, sticky="N") ########################################################################################################### def changePage(self,buttonBool): pages = [self.pageOne,self.pageTwo,self.pageThree] #find current raised page and set to variable 'current' position = pages.index(current) if (postion==0 and buttonBool==False) or (postion==len(pages)-1 and buttonBool==True): show_frame(BlankPage) elif buttonBool==True: pages[position+1].tkraise() else: pages[position-1].tkraise() class BlankPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) app = Program() app.state('zoomed') app.mainloop() 

The changePage function is my attempt to do this, how would I populate it?

0
python oop tkinter tk
Feb 25 '16 at 1:11
source share
1 answer

You are very close to making it all work, after I looked at myself, I could not find a single (not too complicated) way to determine the top Frame , so it would be best to just record the current position:

 def __init__(self, parent, controller): ... self.position = 0 #the index of the pages list 

And to pass buttonBool to changePage , you can from here (Valve gives the best solution in my eyes, since lambda make expressions of the line of code are too long)

 def __init__(self, parent, controller): ... # button commands don't have an event but sometimes you use these callbacks for both .bind and buttons # so having event=None makes it work for both. def go_next(event=None): self.changePage(True) next = ttk.Button(innerFrame, text = "Next", command = go_next) next.grid(row=2, sticky="E") def go_back(event=None): self.changePage(False) back = ttk.Button(innerFrame, text = "Back", command = go_back) back.grid(row=2, sticky="W") ... 

With these two (and implementing self.position in changePage ) you can accomplish what you initially set, all that is below this is the code browser in me.




Although using boolean will work, this strategy of working with extra arguments for callbacks allows you to pass any argument to changePage , so it will probably simplify the conventions of changePage if it receives the change on the pages (so that 1 or -1):

  def go_next(event=None): self.changePage(1) next = ttk.Button(innerFrame, text = "Next", command = go_next) next.grid(row=2, sticky="E") def go_back(event=None): self.changePage(-1) back = ttk.Button(innerFrame, text = "Back", command = go_back) back.grid(row=2, sticky="W") #this is for the last suggestion self.nextButton = next self.backButton = back ... 

then changePage might look like this, although I'm not sure what will happen to self.position if you go to the wrong page:

 def changePage(self,change): pages = [self.pageOne,self.pageTwo,self.pageThree] new_position = self.position + change if (new_postion < 0) or (new_postion <= len(pages)): show_frame(BlankPage) #not sure how you would handle the new position here else: pages[new_position].tkraise() self.position = new_position 

Even better, if you keep a link to the next and back buttons, you can config them to indicate that this is the end / beginning:

 def changePage(self,change): pages = [self.pageOne,self.pageTwo,self.pageThree] new_position = self.position + change if (0 <= new_postion < len(pages)): pages[new_position].tkraise() self.position = new_position else: show_frame(BlankPage) if new_position+1 >= len(pages): self.nextButton.config(text="End") #, state=tk.DISABLED) else: self.nextButton.config(text="Next") #, state=tk.NORMAL) if new_position-1 < 0: self.backButton.config(text="First") #, state=tk.DISABLED) else: self.backButton.config(text="Back") #, state=tk.NORMAL) 

this way you will know when you reach your goal, even if there are no directions from the content. (or you can disable the buttons to prevent passage)

+1
Feb 25 '16 at 19:13
source share



All Articles