I am new to using tkinter and am struggling to get my buttons to render at the very bottom of the screen, evenly spaced out, filling the entire bottom row.
I have been using grid() to try to do this but no luck. I want these three buttons to render without impacting other components of the page(such as the text at the top). I am trying to accomplish a window that has three buttons, each button rendering a different page that you can interact with.
Here is my full code below, I appreciate any insight at all more than you know.
from cgitb import text
import tkinter as tk
from tkinter import ttk
LARGEFONT =("Verdana", 35)
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)
container.grid(row=0, column=0)
container.grid_rowconfigure(0)
container.grid_columnconfigure(0)
# initializing frames to an empty array
self.frames = {}
# iterating through a tuple consisting
# of the different page layouts
for F in (StartPage, Page1, Page2):
frame = F(container, self)
# initializing frame of that object from
# startpage, page1, page2 respectively with
# for loop
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky ="nsew")
self.show_frame(StartPage)
# to display the current frame passed as
# parameter
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 of frame Layout 2
welcome = ttk.Label(self, text ="Welcome!", font = LARGEFONT)
welcome.grid(row = 0, column = 2, )
button1 = ttk.Button(self, text ="Page 1", command = lambda : controller.show_frame(Page1))
button1.grid(row = 9, column = 1, padx = 10, pady = 10)
button2 = ttk.Button(self, text ="Page 2", command = lambda : controller.show_frame(Page2))
button2.grid(row = 9, column = 2, padx = 10, pady = 10)
# second window frame page1
class Page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Page 1", font = LARGEFONT)
label.grid(row = 0, column = 2, )
button1 = ttk.Button(self, text ="StartPage", command = lambda : controller.show_frame(StartPage))
button1.grid(row = 9, column = 1, padx = 10, pady = 10)
button2 = ttk.Button(self, text ="Page 2", command = lambda : controller.show_frame(Page2))
button2.grid(row = 9, column = 2, padx = 10, pady = 10)
# third window frame page2
class Page2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Page 3", font = LARGEFONT)
label.grid(row = 0, column = 2, )
button1 = ttk.Button(self, text ="Page 1", command = lambda : controller.show_frame(Page1))
button1.grid(row = 9, column = 1, padx = 10, pady = 10)
button2 = ttk.Button(self, text ="Startpage", command = lambda : controller.show_frame(StartPage))
button2.grid(row = 9, column = 2, padx = 10, pady = 10)
# Driver Code
app = tkinterApp()
app.geometry("800x425")
app.mainloop()
CodePudding user response:
I made the following changes to your code to get it working:
Gridded the root window so that container
would occupy the entire space in the window.
#Gridding the tkinter window
self.grid_rowconfigure(0, weight = 1)
self.grid_columnconfigure(0, weight = 1)
Made container
expand in all directions using sticky = 'nsew'
.
container.grid(row=0, column=0, sticky = 'nsew')
Modified __init__
and added tkraise
to all the Page classes.
I will use the below block of code for explanation purposes.
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
# label of frame Layout 2
welcome = ttk.Label(self, text ="Welcome!", font = LARGEFONT)
welcome.grid(row = 0, column = 2)
#Creating a frame exclusively for the buttons
self.frame_buttons = tk.Frame(parent)
self.frame_buttons.grid(row = 1, column = 0, columnspan = 3)
self.frame_buttons.grid_remove()
#Gridding self.frame_buttons
self.frame_buttons.grid_columnconfigure((0,1), weight = 1)
self.frame_buttons.grid_rowconfigure(0, weight = 1)
button1 = ttk.Button(self.frame_buttons, text ="Page 1", command = lambda : controller.show_frame(Page1))
button1.grid(row = 0, column = 0, padx = 10, pady = 10)
button2 = ttk.Button(self.frame_buttons, text ="Page 2", command = lambda : controller.show_frame(Page2))
button2.grid(row = 0, column = 1, padx = 10, pady = 10)
def tkraise(self):
self.frame_buttons.grid()
tk.Frame.tkraise(self)
In the __init__
method, self.frame_buttons
is created and all the buttons are added to it. It is displayed using .grid
and then immediately removed with .grid_remove()
. The advantage of using .grid_remove()
is that the grid options are remembered and we can directly use .grid()
to display the frame in future.
In the tkraise
method, the frame is displayed and tk.Frame.tkraise(self)
is used to call the in-built method.
Working Code:
from cgitb import text
import tkinter as tk
from tkinter import ttk
LARGEFONT =("Verdana", 35)
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)
#Gridding the tkinter window
self.grid_rowconfigure(0, weight = 1)
self.grid_columnconfigure(0, weight = 1)
# creating a container
container = tk.Frame(self)
container.grid(row=0, column=0, sticky = 'nsew')
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, Page1, Page2):
frame = F(container, self)
# initializing frame of that object from
# startpage, page1, page2 respectively with
# for loop
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky ="nsew")
self.show_frame(StartPage)
# to display the current frame passed as
# parameter
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 of frame Layout 2
welcome = ttk.Label(self, text ="Welcome!", font = LARGEFONT)
welcome.grid(row = 0, column = 2)
#Creating a frame exclusively for the buttons
self.frame_buttons = tk.Frame(parent)
self.frame_buttons.grid(row = 1, column = 0, columnspan = 3)
self.frame_buttons.grid_remove()
#Gridding self.frame_buttons
self.frame_buttons.grid_columnconfigure((0,1), weight = 1)
self.frame_buttons.grid_rowconfigure(0, weight = 1)
button1 = ttk.Button(self.frame_buttons, text ="Page 1", command = lambda : controller.show_frame(Page1))
button1.grid(row = 0, column = 0, padx = 10, pady = 10)
button2 = ttk.Button(self.frame_buttons, text ="Page 2", command = lambda : controller.show_frame(Page2))
button2.grid(row = 0, column = 1, padx = 10, pady = 10)
def tkraise(self):
self.frame_buttons.grid()
tk.Frame.tkraise(self)
# second window frame page1
class Page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Page 1", font = LARGEFONT)
label.grid(row = 0, column = 2)
#Creating a frame exclusively for the buttons
self.frame_buttons = tk.Frame(parent)
self.frame_buttons.grid(row = 1, column = 0, columnspan = 3)
self.frame_buttons.grid_remove()
#Gridding self.frame_buttons
self.frame_buttons.grid_columnconfigure((0,1), weight = 1)
self.frame_buttons.grid_rowconfigure(0, weight = 1)
button1 = ttk.Button(self.frame_buttons, text ="StartPage", command = lambda : controller.show_frame(StartPage))
button1.grid(row = 0, column = 0, padx = 10, pady = 10)
button2 = ttk.Button(self.frame_buttons, text ="Page 2", command = lambda : controller.show_frame(Page2))
button2.grid(row = 0, column = 1, padx = 10, pady = 10)
def tkraise(self):
self.frame_buttons.grid()
tk.Frame.tkraise(self)
# third window frame page2
class Page2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text ="Page 2", font = LARGEFONT)
label.grid(row = 0, column = 2)
#Creating a frame exclusively for the buttons
self.frame_buttons = tk.Frame(parent)
self.frame_buttons.grid(row = 1, column = 0, columnspan = 3)
self.frame_buttons.grid_remove()
#Gridding self.frame_buttons
self.frame_buttons.grid_columnconfigure((0,1), weight = 1)
self.frame_buttons.grid_rowconfigure(0, weight = 1)
button1 = ttk.Button(self.frame_buttons, text ="Page 1", command = lambda : controller.show_frame(Page1))
button1.grid(row = 0, column = 0, padx = 10, pady = 10)
button2 = ttk.Button(self.frame_buttons, text ="Startpage", command = lambda : controller.show_frame(StartPage))
button2.grid(row = 0, column = 1, padx = 10, pady = 10)
def tkraise(self):
self.frame_buttons.grid()
tk.Frame.tkraise(self)
# Driver Code
app = tkinterApp()
app.geometry("800x425")
app.mainloop()
CodePudding user response:
You are using grid along with pack. You should never mix these two layout managers as it results in unknown buggy behiviour. Maybe your code will work after culling that pack call.