TKInter - Confused about frames and scrolling - python-3.x

I am trying to code a tkinter application that has three frames - a top frame, where the user inputs some text, a dynamically constructed middle section where some pre-analysis is conducted on the text, and a bottom frame where, once the user has selected which option they want in the middle section, the output will be produced.
The problem is that, depending upon the input, there could be around 10-20 (and in the worst case 30) lines displayed and on a small monitor the output will disappear off the screen.
What I would like is for the top (input) and bottom (output) frames to be visible no matter how the screen is re-sized, and for the middle section to scroll (if required) and still allow the user to select their choice.
I am confused as to how to get the middle section to resize when the screen is resized, show a scrollbar if required, and still allow all of the content to be accessed.
I have created a cut-down version here (for simplicity, I have removed the processing methods and have instead created some fake output in a loop that resembles what the actual middle section would look like).
Please ignore the hideous colour-scheme - I was just trying to understand which frame went where (I will remove the colours as soon as I can!)
Thank you for any suggestions...
import tkinter as tk
from tkinter import scrolledtext
class MyApp(tk.Tk):
def __init__(self, title="Sample App", *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title(title)
self.configure(background="Gray")
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
# Create the overall frame:
master_frame = tk.Frame(self, bg="Light Blue", bd=3, relief=tk.RIDGE)
master_frame.grid(sticky=tk.NSEW)
master_frame.rowconfigure([0, 2], minsize=90) # Set min size for top and bottom
master_frame.rowconfigure(1, weight=1) # Row 1 should adjust to window size
master_frame.columnconfigure(0, weight=1) # Column 0 should adjust to window size
# Create the frame to hold the input field and action button:
input_frame = tk.LabelFrame(master_frame, text="Input Section", bg="Green", bd=2, relief=tk.GROOVE)
input_frame.grid(row=0, column=0, padx = 5, pady = 5, sticky=tk.NSEW)
input_frame.columnconfigure(0, weight=1)
input_frame.rowconfigure(0, weight=1)
# Create a frame for the middle (processing) section.
middle_frame = tk.LabelFrame(master_frame, text = "Processing Section")
middle_frame.grid(row=1, column=0, padx=5, pady=5, sticky=tk.NSEW)
# Create the frame to hold the output:
output_frame = tk.LabelFrame(master_frame, text="Output Section", bg="Blue", bd=2, relief=tk.GROOVE)
output_frame.grid(row=2, column=0, columnspan=3, padx=5, pady=5, sticky=tk.NSEW)
output_frame.columnconfigure(0, weight=1)
output_frame.rowconfigure(0, weight=1)
# Add a canvas in the middle frame.
self.canvas = tk.Canvas(middle_frame, bg="Yellow")
self.canvas.grid(row=0, column=0)
# Create a vertical scrollbar linked to the canvas.
vsbar = tk.Scrollbar(middle_frame, orient=tk.VERTICAL, command=self.canvas.yview)
vsbar.grid(row=0, column=1, sticky=tk.NS)
self.canvas.configure(yscrollcommand=vsbar.set)
# Content for the input frame, (one label, one input box and one button).
tk.Label(input_frame,
text="Please type, or paste, the text to be analysed into this box:").grid(row=0, columnspan = 3, sticky=tk.NSEW)
self.input_box = scrolledtext.ScrolledText(input_frame, height=5, wrap=tk.WORD)
self.input_box.columnconfigure(0, weight=1)
self.input_box.grid(row=1, column=0, columnspan = 3, sticky=tk.NSEW)
tk.Button(input_frame,
text="Do it!",
command=self.draw_choices).grid(row=2, column=2, sticky=tk.E)
# Content for the output frame, (one text box only).
self.output_box = scrolledtext.ScrolledText(output_frame, width=40, height=5, wrap=tk.WORD)
self.output_box.grid(row=0, column=0, columnspan=3, sticky=tk.NSEW)
def draw_choices(self):
""" This method will dynamically create the content for the middle frame"""
self.option = tk.IntVar() # Variable used to hold user's choice
self.get_input_text()
for i in range(30):
tk.Radiobutton(self.canvas,
text=f"Option {i + 1}: ", variable=self.option,
value=i,
command=self.do_analysis
).grid(row=i, column=0, sticky=tk.W)
tk.Label(self.canvas,
text=f"If you pick Option {i + 1}, the output will look like this: {self.shortText}.",
anchor=tk.W
).grid(row=i, column=1, sticky=tk.W)
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
def get_input_text(self):
""" Will get the text from the input box and also create a shortened version to display on one line"""
screenWidth = 78
self.input_text = self.input_box.get(0.0, tk.END)
if len(self.input_text) > screenWidth:
self.shortText = self.input_text[:screenWidth]
else:
self.shortText = self.input_text[:]
self.shortText = self.shortText.replace('\n', ' ') # strip out carriage returns just in case
def do_analysis(self):
"""This will ultimately process and display the results"""
option = self.option.get() # Get option from radio button press
output_txt = f"You picked option {option + 1} and here is the output: \n{self.input_text}"
self.output_box.delete(0.0, tk.END)
self.output_box.insert(0.0, output_txt)
if __name__ == "__main__":
app = MyApp("My Simple Text Analysis Program")
app.mainloop()

I understand that you can't mix grid and pack geometries in the same container, and that a scrollbar must be attached to a canvas, and objects to be placed on that canvas must therefore be in yet another container so, attempting to follow Bryan's example, I created a minimal version of what I want - window with three sections - top, middle and bottom. The Top and bottom sections will contain a simple text field, the middle section will contain dynamic content and must be able to scroll as required.
Imports:
ScrollbarFrame
Extends class tk.Frame to support a scrollable Frame]
import tkinter as tk
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("A simple GUI")
# Top frame
self.top_frame = tk.Frame(self, bg="LIGHT GREEN")
self.top_frame.pack(fill=tk.X)
tk.Label(self.top_frame, bg=self.top_frame.cget('bg'),
text="This is a label on the top frame")\
.grid(row=0, columnspan=3, sticky=tk.NSEW)
# Middle Frame
# Import from https://stackoverflow.com/a/62446457/7414759
# and don't change anything
sbf = ScrollbarFrame(self, bg="LIGHT BLUE")
sbf.pack(fill=tk.X, expand=True)
# self.middle_frame = tk.Frame(self, bg="LIGHT BLUE")
self.middle_frame = sbf.scrolled_frame
# Force scrolling by adding multiple Label
for _ in range(25):
tk.Label(self.middle_frame, bg=self.middle_frame.cget('bg'),
text="This is a label on the dynamic (middle) section")\
.grid()
# Bottom Frame
self.bottom_frame = tk.Frame(self, bg="WHITE")
self.bottom_frame.pack(fill=tk.X)
tk.Label(self.bottom_frame, bg=self.bottom_frame.cget('bg'),
text="This is a label on the bottom section")\
.grid(row=0, columnspan=3, sticky=tk.NSEW)
if __name__ == '__main__':
App().mainloop()

Related

tkinter text widget increasing size of frame

I am trying to create a GUI for an application I am making and for some reason that I cannot figure out, the text widget that is inside the message_space frame is increasing the size of the message_space frame and reducing the size of the friends_space frame. I want the friends_space frame to take up 1/4th of the window size and the message_space frame to take up the remaining 3/4ts of the window size.
The red is the friends_space frame, the blue is the message_space frame.
This is how I would like the sizing of the frames to be.
This is what is happening when I add the text box.
Code
from tkinter import *
class app:
def __init__(self, master):
self.master = master
master.title("PyChat")
master.geometry("800x500")
master.configure(bg="grey")
master.resizable(0, 0)
master.grid_columnconfigure(0, weight=1)
master.grid_columnconfigure(1, weight=3)
master.grid_rowconfigure(0, weight=1)
self.friends_space = Frame(master, bg="red")
self.friends_space.grid(row=0, column=0, sticky=NSEW)
self.chat_space = Frame(master, bg="blue")
self.chat_space.grid(row=0, column=1, columnspan=3, sticky=NSEW)
self.message_area = Text(self.chat_space)
self.message_area.grid(row=0, column=0)
root = Tk()
my_gui = app(root)
root.mainloop()
If you're using grid, you divide your UI into four uniform-width columns (using the uniform option), then have the text widget span three.
You should also start with a small text widget that can grow into the space. Otherwise tkinter will try to preserve the large size and start removing space from the other widgets in order to try to make everything fit.
Here's an example based on your original code. However, I'm using pack for the text widget instead of grid because it requires fewer lines of code. I've also reorganized the code a bit. I find that grouping calls to grid together makes layout easier to grok.
I've also removed the restriction on resizing. There's rarely a good idea to limit the user's ability to resize the window. Plus, it allows you to see that the resulting UI is responsive.
from tkinter import *
class app:
def __init__(self, master):
self.master = master
master.title("PyChat")
master.geometry("800x500")
master.configure(bg="grey")
master.grid_columnconfigure((0,1,2,3), uniform="uniform", weight=1)
master.grid_rowconfigure(0, weight=1)
self.friends_space = Frame(master, bg="red")
self.chat_space = Frame(master, bg="blue")
self.friends_space.grid(row=0, column=0, sticky=NSEW)
self.chat_space.grid(row=0, column=1, columnspan=3, sticky=NSEW)
self.message_area = Text(self.chat_space, width=1, height=1)
self.message_area.pack(fill="both", expand=True)
root = Tk()
my_gui = app(root)
root.mainloop()

Tkinter - Expanding frame after (interactively) adding elements to it

I have the following code:
from tkinter import *
DEF_CHANNELS = {'iris': (255, 0, 0), 'sclera': (0, 255, 0), 'pupil': (0, 0, 255)}
class GUI(Tk):
def __init__(self, init_source, init_target, *args, **kw):
super().__init__(*args, **kw)
self.frame = Frame(self, height=400, width=500)
self.frame.pack(fill=BOTH, expand=YES)
self.channel_frame = Frame(self.frame, height=200, width=500, pady=16)
self.channel_frame.grid(column=0, row=0, columnspan=2)
self.channel_label = Label(self.channel_frame, text="Channel")
self.channel_label.grid(column=0, row=0)
self.colour_label = Label(self.channel_frame, text="Colour")
self.colour_label.grid(column=1, row=0)
self.channel_frames = []
for channel, colour in DEF_CHANNELS.items():
self.add_channel_frame(channel, colour)
self.channel_button = Button(self.channel_frame, text="+", command=self.add_channel_frame)
self.channel_button.grid(column=0, row=len(self.channel_frames) + 1)
def add_channel_frame(self, def_channel="", def_colour=""):
pair_frame = ChannelColourFrame(self.channel_frame, def_channel=def_channel, def_colour=def_colour, height=100, width=500, pady=2)
pair_frame.grid(column=0, row=len(self.channel_frames) + 1, columnspan=2)
self.channel_frames.append(pair_frame)
class ChannelColourFrame(Frame):
def __init__(self, *args, def_channel="", def_colour="", **kw):
super().__init__(*args, **kw)
self.channel_txt = Entry(self, width=30)
self.channel_txt.insert(END, def_channel)
self.channel_txt.grid(column=0, row=0)
self.colour_txt = Entry(self, width=30)
self.colour_txt.insert(END, def_colour)
self.colour_txt.grid(column=1, row=0)
self.color_picker_button = Button(self, text="\u2712")
self.color_picker_button.grid(column=2, row=0)
self.remove_button = Button(self, text="-", command=self.remove)
self.remove_button.grid(column=3, row=0)
def remove(self):
self.master.master.master.channel_frames.remove(self)
self.destroy()
gui = GUI('', '')
gui.mainloop()
The idea is to have a Frame that starts with 3 default text Entry pairs, which a user can arbitrarily remove/add. For the most part it works fine, but with one big problem. The Frame (self.channel_frame) never expands past its initial height, which causes problems when more than the initial 3 Entry pairs appear on it.
How do I make the entire Frame fit to the Entry pairs every time one is removed/added?
As an additional question, \u2712 appears as a box on my button, but it's supposed to be the black nib symbol (✒). Why isn't the symbol showing up despite being part of unicode?
You aren't creating any new rows, so it's not going to grow. At the start, you create three channel frames, and they are put in rows 0, 1, and 2. You then add a "+" button in row 4.
When you click the "+" button, it adds a new row at len(self.channel_frames) + 1. Since len(self.channel_frames) is 3, it adds the new frame at row 4, which is on top of the "+" button. Thus, you aren't adding a new row.
If you move the "+" button out of the frame, or move it down each time you add a new row, your code works fine.
For example:
def add_channel_frame(self, def_channel="", def_colour=""):
pair_frame = ChannelColourFrame(self.channel_frame, def_channel=def_channel, def_colour=def_colour, height=100, width=500, pady=2)
pair_frame.grid(column=0, row=len(self.channel_frames) + 1, columnspan=2)
self.channel_frames.append(pair_frame)
self.channel_button.grid(column=0, row=len(self.channel_frames)+1)
As an additional question, \u2712 appears as a box on my button, but it's supposed to be the black nib symbol (✒). Why isn't the symbol showing up despite being part of unicode?
Probably because the font you're using doesn't have that symbol. Try using a different font.

Positioning different sets of entries next to each other in python tkinter

I use a Tkinter frame in python, and on one of the pages I need to display 2 sets of entries, one next to the other, where the number of entries is equal to the number in range (in the full program is a changing variable, so each time the number of entries changes). I use the for loop to do it.
However, when I try to pack the entries into the frame, the 2 sets of 3 entries are shown in one single column of 6 entries, instead of showing 2 columns with 3 rows of entries each.
If I adjust the packs to the left and right sides of the frame, each set of entries then is shown in 1 row, and has 3 columns, which is not needed.
When I use .place or .grid instead of .pack, then for each set only one single entry is shown (I guess all 3 entries are just placed in a single defined location ex. (x = 550, y = 80), so that 3 entries "overlap" into one)
I guess I need to write a more sophisticated "for loop" function and use .grid or .place positioning, so that all 3 entries will be displayed in a column one after the other.
Or I'm also thinking that using .pack and inserting the entries into a new frame inside the first frame, and then position these 2 frames one next to another might work. But again, I tried to create an extra frame inside the first page, and it didn't work.
Any observations and tips would be highly appreciated!
Here is the full code, so you might try playing around with it and see the whole picture. (sorry for a mess in imports, I also have to sort it out)
P.S. It is a part of a bigger code, where I need to use more then 1 page, so this code is the smallest that works - if I there would be only a single frame in the program, I would have no problem arranging the entries as I need. The problem is that I don't know how to arrange the entries is this particular structure.
import tkinter as tk
from tkinter import font as tkfont
import traceback
from tkinter import messagebox
from pandastable.core import Table
from pandastable.data import TableModel
from tkinter import *
from tkinter import ttk
import tkinter as Tkinter
import tkinter.ttk as ttk
LARGE_FONT= ("Verdana", 12)
class MyTable(Table):
"""
Custom table class inherits from Table.
You can then override required methods
"""
def __init__(self, parent=None, **kwargs):
Table.__init__(self, parent, **kwargs)
return
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")
# 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
self.geometry('800x600+200+100')
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, 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()
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=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button2 = tk.Button(self, text="Go to Page Two",
command=lambda: controller.show_frame("PageTwo"))
button2.place(x = 20, y = 50)
entries = [Entry(self, font =('Calibri', 7 )) for _ in range(3)]
for entry in entries:
#entry.place(x = 400, y = 80)
entry.pack()
entries_date = [Entry(self, font =('Calibri', 7 )) for _ in range(3)]
for entry in entries_date:
#entry.place(x = 550, y = 80)
entry.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 2", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
If you're trying to create rows and columns, there are two generally accepted ways to do it:
make each row a frame, and pack the entries along a side
use grid to create rows and columns.
The first is best if your columns don't need to line up, the second is best if your columns do need to line up. Though, you also have to take into consideration what else you're putting in the frame -- you can't use both grid and pack on widgets that have the same master.
Note: If you're creating identical widgets in each row, then as a side effect the columns will line up even when you use pack.
Example using pack:
entries = []
entry_frame = Frame(self)
entry_frame.pack(side="top", fill="x")
for column in range(3):
entry = Entry(entry_frame, font=('Calibri', 7))
entry.pack(side="left", fill="both", expand=True)
entries.append(entry)
entries_date = []
entry_date_frame = Frame(self)
entry_date_frame.pack(side="top", fill="x")
for column in range(3):
entry = Entry(entry_date_frame, font=('Calibri', 7))
entry.pack(side="left", fill="both", expand=True)
entries_date.append(entry)
Example using grid:
entries = []
for column in range(3):
entry = Entry(self, font=('Calibri', 7))
entry.grid(row=0, column=column, sticky="ew")
entries.append(entry)
entries_date = []
for column in range(3):
entry = Entry(self, font=('Calibri', 7))
entry.grid(row=1, column=column, sticky="ew")
entries_date.append(entry)

Tkinter Python Frame with Scroll bar

I have below code which will create Label and Entry widgets. Also I created Scroll bar for this window but both scroll bars are not working.
Please let me know why the scroll bar is disabled. Did the code is doing wrong ?
Below is my code which will create 50 labels and entry widgets but still scroll bars are not enabled.
import tkinter as tk
from tkinter import ttk
class DoubleScrollbarFrame(ttk.Frame):
def __init__(self, master, **kwargs):
'''
Initialisation. The DoubleScrollbarFrame consist of :
- an horizontal scrollbar
- a vertical scrollbar
- a canvas in which the user can place sub-elements
'''
ttk.Frame.__init__(self, master, **kwargs)
# Canvas creation with double scrollbar
self.hscrollbar = ttk.Scrollbar(self, orient=tk.HORIZONTAL)
self.vscrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL)
self.sizegrip = ttk.Sizegrip(self)
self.canvas = tk.Canvas(self, bd=0, highlightthickness=0,
yscrollcommand=self.vscrollbar.set,
xscrollcommand=self.hscrollbar.set)
self.vscrollbar.config(command=self.canvas.yview)
self.hscrollbar.config(command=self.canvas.xview)
def pack(self, **kwargs):
'''
Pack the scrollbar and canvas correctly in order to recreate the
same look as MFC's windows.
'''
self.hscrollbar.pack(side=tk.BOTTOM, fill=tk.X, expand=tk.FALSE)
self.vscrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=tk.FALSE)
self.sizegrip.pack(in_=self.hscrollbar, side=tk.BOTTOM, anchor="se")
self.canvas.pack(side=tk.LEFT, padx=5, pady=5,
fill=tk.BOTH, expand=tk.TRUE)
ttk.Frame.pack(self, **kwargs)
def get_frame(self):
'''
Return the "frame" useful to place inner controls.
'''
return self.canvas
if __name__ == '__main__':
# Top-level frame
root = tk.Tk()
root.title("Double scrollbar with tkinter")
root.minsize(width=600, height=600)
frame = DoubleScrollbarFrame(root, relief="sunken")
# Add controls here
subframe = ttk.Frame(frame.get_frame())
txt = ttk.Label(subframe, text="Add things here !")
for i in range(50):
ttk.Label(subframe, text="Field %d: " % i).grid(row=i, column=0,
sticky="w")
ttk.Entry(subframe, width=25).grid(row=i, column=1, sticky="ew")
subframe.pack(padx=15, pady=15, fill=tk.BOTH, expand=tk.TRUE)
frame.pack(padx=5, pady=5, expand=True, fill=tk.BOTH)
# launch the GUI
root.mainloop()

Python frames tkinter

Im having troubles with tkinter frames
The folowing code must display labels at left side and there should be more space the button and the label , there is something wrong with my column/row setup. What am i doing wrong?
What is the correct way for a program to display information? 1 global frame with several smaller frames in it? With tkinter when using a menu with page 1 page 2 and page 3 ,
page 1 has 3 input fields , child of FramePage1 , page 2 has 2 buttons child of FramePage2, page 3 has one big text field child of FramePage3. Is it the correct way to use for changing the pages
#menu tab1 -> command #calls function page1
def page1():
self.Framepage2.grid_forget()
self.Framepage1.grid()
#content of the page
or are there other ways to use different layout style pages?
import tkinter
import tkinter as tk
class sjabloon():
def __init__(self):
#make window
self.win = tk.Tk()
self.win.geometry("600x600+10+10")
#make top frame
self.frame_header = tk.Frame(self.win, background='black', width=600, height=50)
self.frame_header.grid(column=0, row=0 , columnspan= 10)
#make body frame
self.frame_body = tk.Frame(self.win, width=600, height=400)
self.frame_body.grid(column=0, row=1 , columnspan= 10)
#button1 select
tk.Label(self.frame_body, text="Select:").grid(column=0, row=2, stick='W')
self.button1 = tk.Button(self.frame_body, text="Select")
self.button1.grid(row=2, column=5, stick='W')
#button1 select
tk.Label(self.frame_body, text="Select:").grid(column=0, row=3, stick='W')
self.button2 = tk.Button(self.frame_body, text="Select")
self.button2.grid(row=4, column=5, stick='W')
#button submit
self.submit = tk.Button(self.frame_body, text="Start")
self.submit.grid(row=10, column=9, stick='W')
#make body footer
self.frame_footer = tk.Frame(self.win, background='yellow', width=600, height=50)
self.frame_footer.grid(column=0, row=3 , columnspan= 10)
if __name__ == "__main__":
sjabloon = sjabloon()
I suggest you to follow this tkinter GUI tutorial, he makes a pretty big app and even if it's not what you exactly looking for, it will help you.
In the part 4, he make a multiple frame architecture in the tkinter GUI.
For switching "pages", i know 2 choices (there's more i think but i don't know them, i'm still a beginner). You can create all the frames inside a window/Frame and raise to the front the one you want (that's in the tutorial part 4) or you can destroy the widgets "Page 1" inside the body frame and create the widgets "Page 2" inside it (obviously in methods/functions to let you switch between the pages).
For your first problem, i'm not sure if i understand your problem, you want more space around your button widget ? if that's what you want, you can use the option padx=(leftPadx,RightPadx) like that :
self.button1.grid(row=2, column=5, stick='W', padx=(50,0))
EDIT : i made a little architecture for you (from what i learn in that tutorial)
Basically, you create all the "Page", you add them in the bodyFrame and you raise to the front the one you want. To achieve that, for each "Page", you create a class that inherits tk.Frame and you add an instance of that class in the mainWindow
import tkinter as tk
from tkinter import ttk
LARGE_FONT = ("Verdana 12")
NORM_FONT = "Verdana 10"
SMALL_FONT = ("Verdana 8")
ERROR_404 = "Error 404 : Page not found !"
class sjabloon(tk.Tk):
def __init__(self, *args, **kwargs):
#make window
tk.Tk.__init__(self, *args, **kwargs)
self.geometry("600x600+10+10")
#make top frame
self.frame_header = tk.Frame(self, background='black', width=600, height=50)
self.frame_header.grid(column=0, row=0 , columnspan= 10)
#make body frame
container = tk.Frame(self, width=600, height=400)
container.grid(column=0, row=1 , columnspan= 10)
#list of Pages
self.frames = {}
#everytime you create a "Page", you add it there
for F in (StartPage, HomePage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=1, column = 0, sticky="nsew", columnspan= 10)
self.show_page("StartPage")
#make body footer
self.frame_footer = tk.Frame(self, background='yellow', width=600, height=50)
self.frame_footer.grid(column=0, row=3 , columnspan= 10)
def show_page(self, page_name):
"""
let us use the NAME of the class to display(the function show_frame
use directly the class).
when we use the classe name, we can put our classes in defferent
files
"""
for F in self.frames:
if F.__name__ == page_name:
self.show_frame(F)
return
print(ERROR_404)
def show_frame(self, cont):
"""raise to the front the frame we want
:param cont: the frame
"""
frame = self.frames[cont]
frame.tkraise()
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#button1 select
tk.Label(self, text="Select:").grid(column=0, row=2, stick='W')
self.button1 = tk.Button(self, text="Select")
self.button1.grid(row=2, column=5, stick='W', padx=(50,0))
#button1 select
tk.Label(self, text="Select:").grid(column=0, row=3, stick='W')
self.button2 = tk.Button(self, text="Select")
self.button2.grid(row=4, column=5, stick='W', padx=(50,0))
#button submit
self.submit = tk.Button(self, text="Start")
self.submit.grid(row=10, column=9, stick='W')
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="""ALPHA application.
use at your own risk. There is no promise
of warranty""", font=LARGE_FONT)
label.pack(pady=10, padx=10)
button1 = ttk.Button(self, text="Agree",
command=lambda: controller.show_page("HomePage"))
button1.pack()
button2 = ttk.Button(self, text="Disagree",
command=controller.destroy)
button2.pack()
if __name__ == "__main__":
sjabloon = sjabloon()
sjabloon.mainloop()

Resources