import tkinter as tk
class program(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args,**kwargs)
self.title("Staff Management System")
self.geometry("1280x720")
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.frames = {}
#frame that will hold all the elements
container = tk.Frame(self)
container.grid(row=0,column=0)
container.columnconfigure(0,weight=1)
container.rowconfigure(0,weight=1)
#listing frames (pages) to be controlled
for F in (homePage, staffLogin):
frame = F(parent=container, controller=self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky = "nsew")
self.show_frame(homePage)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
class homePage(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent,*args, **kwargs)
for i in range(4):
self.columnconfigure(i, weight=1)
for i in range(4):
self.rowconfigure(i, weight=1)
self.config(background="red")
self.configure(background="red")
promotionsButton = tk.Button(self, text="Promotions", height = 4)
promotionsButton.grid(row=2, column = 0, sticky='w')
staffLoginButton = tk.Button(self, text="Staff Login", width = 50, height = 20, command= lambda: controller.show_frame(staffLogin))
staffLoginButton.grid(row=1, column=1)
managerLoginButton = tk.Button(self, text="Manager Login", width = 50, height = 20)
managerLoginButton.grid(row=1,column=2)
class staffLogin(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent, *args, **kwargs)
self.controller = controller
for i in range(128):
self.columnconfigure(i,weight=1)
for i in range(128):
self.rowconfigure(i,weight=1)
userIDLabel = tk.Label(self, text = "UserID:")
userIDInput = tk.Entry(self, width=50, font=("Helvectia",16))
userIDLabel.grid(sticky="W", row=67,column=59)
userIDInput.grid(row=67, column=60)
userPasswordLabel = tk.Label(self, text = "Password:")
userPasswordInput = tk.Entry(self,width=50, font=("Helvectia",16))
userPasswordLabel.grid(sticky="W", row=70, column=59)
userPasswordInput.grid(row=70, column=60)
loginButton = tk.Button(self, text="Login", height=2, width=7)
loginButton.grid(sticky="E",row = 71, column=60)
thing = program()
thing.mainloop()
for each "page" i want the frame to fill out the entire window but when i run my program, my page does not fill out the whole window. i've tried setting the weight of both the root (self) and the containers that are holding my frames but to no avail. i am unsure as of what to do next. in each page i ran the "self.configure" method in order to check whether the frame has filled out the entire window but it has not
The frames are filling your container, but your container isn't filling the window. The container is a child of self, and you use grid to add the container, but you never set the weight of the row and column for self, so it defaults to zero. That means that the container won't be allocated any extra space which results in it being centered in the window. You also don't set the sticky attribute, so even if it was allocated the space it wouldn't use it.
Personally, I recommend using pack for container since it requires fewer lines of code. However, to use grid you need to do it like this:
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
container.grid(row=0,column=0, sticky="nsew")
Related
import tkinter as tk
class program(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args,**kwargs)
self.title("Staff Management System")
self.geometry("1280x720")
self.columnconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.frames = {}
#frame that will hold all the elements
container = tk.Frame(self)
container.grid(row=1,column=0,)
for i in range(128):
container.columnconfigure(i,weight=1)
for i in range(128):
container.rowconfigure(i,weight=1)
#listing frames (pages) to be controlled
for F in (homePage, staffLogin):
frame = F(parent=container, controller=self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky = "nsew")
self.show_frame(staffLogin)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
class homePage(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent,*args, **kwargs)
self.controller = controller
promotionsButton = tk.Button(self, text="Promotions", height = 4)
promotionsButton.grid(row=1, column = 128, sticky='w')
staffLoginButton = tk.Button(self, text="Staff Login", width = 50, height = 20)
staffLoginButton.grid(row=1, column=1)
managerLoginButton = tk.Button(self, text="Manager Login", width = 50, height = 20)
managerLoginButton.grid(row=1,column=2)
class staffLogin(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent, *args, **kwargs)
self.controller = controller
userIDLabel = tk.Label(self, text = "UserID:")
userIDInput = tk.Entry(self, width=50, font=("Helvectia",16))
userIDLabel.grid(sticky="W", row=67,column=59)
userIDInput.grid(row=67, column=60)
userPasswordLabel = tk.Label(self, text = "Password:")
userPasswordInput = tk.Entry(self,width=50, font=("Helvectia",16))
userPasswordLabel.grid(sticky="W", row=70, column=59)
userPasswordInput.grid(row=70, column=60)
loginButton = tk.Button(self, text="Login", height=2, width=7)
loginButton.grid(sticky="E",row = 71, column=60)
thing = program()
thing.mainloop()
im trying to use the container column and row configure methods in order to create 128 'boxes' that i am able to grid widgets in for each of my pages. However, it doesn't work when i run the program, when i try passing 'parent' instead of 'self' when i create my widgets in my different pages, my show_frame function doesnt work and instead it displays the widgets from both of my pages at the same time.
You're calling rowconfigure and columnconfigure on the container, but the container only has a single row and a single column that is used to hold each "page". You need to be calling those methods on each page rather than on the container.
class homePage():
def __init__(self, parent, controller, *args, **kwargs):
...
for i in range(128):
self.columnconfigure(i,weight=1)
for i in range(128):
self.rowconfigure(i,weight=1)
import tkinter as tk
class program(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args,**kwargs)
self.title("Staff Management System")
self.geometry("1280x720")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.frames = {}
#frame that will hold all the elements
container = tk.Frame(self)
container.grid(row=0,column=0, sticky="nsew")
container.columnconfigure(0,weight=1)
container.rowconfigure(0,weight=1)
container.configure(background="blue")
#listing frames (pages) to be controlled
for F in (homePage, staffLogin):
frame = F(parent=container, controller=self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(homePage)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
class homePage(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent,*args, **kwargs)
for i in range(5):
self.columnconfigure(i, weight=1)
for i in range(5):
self.rowconfigure(i, weight=1)
promotionsButton = tk.Button(self, text="Promotions", height = 4)
promotionsButton.grid(row=5, column =0, sticky='w')
staffLoginButton = tk.Button(self, text="Staff Login", width = 50, height = 20, command= lambda: controller.show_frame(staffLogin))
staffLoginButton.grid(row=2, column=1)
managerLoginButton = tk.Button(self, text="Manager Login", width = 50, height = 20)
managerLoginButton.grid(row=2,column=2)
class staffLogin(tk.Frame):
def __init__(self, parent, controller, *args, **kwargs):
tk.Frame.__init__(self,parent, *args, **kwargs)
self.controller = controller
for i in range(128):
self.columnconfigure(i,weight=1)
for i in range(128):
self.rowconfigure(i,weight=1)
self.staffLabel = tk.Label(self, text = "Staff Login", font=("Helvectia", 24))
self.staffLabel.grid(row = 40, column=60)
self.userIDLabel = tk.Label(self, text = "UserID:")
self.userIDLabel.grid(sticky="W", row=67,column=59)
self.userIDInput = tk.Entry(self, width=50, font=("Helvectia",16))
self.userIDInput.grid(row=67, column=60)
self.userPasswordLabel = tk.Label(self, text = "Password:")
self.userPasswordLabel.grid(sticky="W", row=70, column=59)
self.userPasswordInput = tk.Entry(self,width=50, font=("Helvectia",16))
self.userPasswordInput.grid(row=70, column=60)
self.showPassword = tk.Button(self, text="Show Password", command=self.togglePassword())
self.showPassword.grid(sticky="W", row=71, column=60)
self.loginButton = tk.Button(self, text="Login", height=2, width=7)
self.loginButton.grid(sticky="E",row = 71, column=60)
self.backButton = tk.Button(self, text="Back To Main Menu", height=4, command= lambda: controller.show_frame(homePage))
self.backButton.grid(row=128, column=0)
def togglePassword(self):
if self.userPasswordLabel.cget("show") == "*":
self.userPasswordLabel.config(show= "")
self.showPassword.config(text="Hide Password")
else:
self.userPasswordLabel.config(show="")
self.showPassword.config(text="Show Password")
thing = program()
thing.mainloop()
im trying to create a function that runs when clicked inside of my "staff login" page. However, due to me using a new method of programming tkinter to be able to switch pages, I am unsure of how to get functions for buttons to work. currently, i get an error saying that the methods that i am trying to call do not exist. im not sure of what to do in order to be able to run functions inside of pages
Just started learning tkinter and im tackling on grid management.
I set the a frame to have 1 weight on column 0, therefore I expected label1 to be stretched to the end of the frame, then label2 added on column 1 with the length relative to its text size.
expected output: https://gyazo.com/65cf907e2cdea07d08844bdc8c62c7b2
output: https://gyazo.com/3c9e9c9f86372e01e96283545387c51e
Heres my code:
import tkinter as tk
class App(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)
frame_list = (MenuFrame,
)
self.geometry("1024x768")
self.frames = {}
for F in frame_list:
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("MenuFrame")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class MenuFrame(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.create_widgets(self)
def create_widgets(self, parent):
frame = tk.Frame(self, bg="white")
frame.grid_columnconfigure(0, weight=1)
frame.grid_rowconfigure(0, weight=1)
label1 = tk.Label(frame, text="Label one", bg="red")
label2 = tk.Label(frame, text="Label two", bg="blue", fg="white")
frame.grid(row=0, column=0, sticky="nsew")
label1.grid(row=0, column=0)
label2.grid(row=0, column=1)
if __name__ == "__main__":
app = App()
app.mainloop()
You are properly configuring the weight for frame. However, frame hasn't been properly configured to fill the window. Because of that, it's just barely wide enough for the two labels and thus the weight has no effect.
Since frame seems to be the only widget inside the class MenuFrame, I would use pack instead of grid since it only requires one line:
frame.pack(fill="both", expand=True)
If you prefer using grid, then you need to also configure the weight for its parent.
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
frame.grid(row=0, column=0, sticky="nsew")
The buttons and labels will not show up in my window. If I delete self from the parenthesis (or insert controller instead), the buttons will show up. However, the buttons do not raise the underlying window to the front as it is supposed to. I used a similar code that used pack, and it worked well. I can't seem to find the problem of why using grid won't work. I'm a bit of a beginner to tkinter so perhaps I'm missing something obvious.
import tkinter as tk
LARGE_FONT= ("Verdana", 12)
NORM_FONT= ("Verdana", 10)
SMALL_FONT= ("Verdana", 8)
class mGui(tk.Tk):
def __init__(self, *args, **kargs):
tk.Tk.__init__(self, *args, **kargs)
container = tk.Frame(self)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
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)
label_1 = tk.Label(self, text = "Start Page", font = LARGE_FONT)
label_1.grid(row = 0, column = 0)
button1 = tk.Button(self,text = "Go", command = lambda: controller.show_frame(PageOne))
button1.grid(row = 1, column = 0)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label_1 = tk.Label(self, text = "Page One", font = LARGE_FONT)
label_1.grid(row = 1, column = 4)
button1 = tk.Button(self, text = "Go Back", command = lambda: controller.show_frame(StartPage))
button1.grid(row = 4, column = 1)
app = mGui()
app.mainloop()
You need to add a call to the grid() layout manager for the container Frame as shown:
.
.
.
class mGui(tk.Tk):
def __init__(self, *args, **kargs):
tk.Tk.__init__(self, *args, **kargs)
container = tk.Frame(self)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
container.grid() # ADD THIS.
.
.
.
So I have read a few posts on here and have tried them all. The current method I have attempted is storing the data in the controller:
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.app_data = {"building": tk.StringVar()}
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):
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()
I then have my PageOne receive input from user as to what building they want:
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
#buidling
bldg_label = ttk.Label(self, text="Building Name (ie. ACAD):", font=LARGE_FONT)
bldg_label.grid(row=0, column=0, padx=2, pady = 10)
self.bldg_entry =ttk.Entry(self,width = 6, textvariable = self.controller.app_data["building"])
self.bldg_entry.grid(row=0, column=1, padx=2, pady=10)
button1 = ttk.Button(self, text="next", command = lambda: controller.show_frame(PageTwo))
button1.grid(row = 1, column = 0)
Lastly I want to display the building they typed into the entry box into a label like so:
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
bldg = self.controller.app_data["building"].get()
bldg_label = ttk.Label(self, text = "Building: " + str(bldg), font=LARGE_FONT)
bldg_label.grid(row = 0, column =0)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.grid(row = 1, column =0)
I know there needs to be some sort of updating but I just can't seem to get the right structure to make this work. The label prints: Building: with nothing in it. My question is how can I get the data that is stored in the dictionary to update the building label in the SecondPage? Any help would be greatly appreciated!