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)
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.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
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")
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.
.
.
.
With the if-statement that I have put in, it would only display the lose statement even if it is correct.
I'm not sure if the way I wrote the statement is correct.
I'm trying to make it that when pressing start both labels would show a number between 1 to 21.
Also, if it's possible, I want to make it that when the hit button is pressed, a number would be added to the label. For example, pressing hit would add 10 + 5, then display the total.
LOCATED IN CLASS TTY:
import tkinter as tk
k = 10
Q = 10
J = 10
A = 11 or 1
class WINDOW(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Memory") #sets the window title
container = tk.Frame(self)#Name of frame to refer to
container.pack(side="top", fill="both", expand=True)#size of window
container.grid_rowconfigure(0, weight=4)#size of window
container.grid_columnconfigure(0, weight=4)
self.frames = {}
for F in (MainMenu, tty):
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("MainMenu")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class MainMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = 'white')
label = tk.Label(self, text="Memory",font=(15),
borderwidth=5, relief="solid")
label.pack(side="top", fill="y", pady=15, padx=270)
label.pack(fill="both")
button1 = tk.Button(self, text="Start", relief="solid",
borderwidth=5,width=30,
font=(17),command=lambda:
controller.show_frame("tty"))
button1.pack()
button3 = tk.Button(self,
text="Quit",relief="solid",borderwidth=4,width=30,font=(17),command = quit)
button3.place(x="420", y ="50")
button3.pack()
class tty(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "white")
def win():
if score > deal:
tts = tk.Label(self, text="win", font=(20))
tts.pack()
else:
lose = tk.Label(self, text="lose", font=(10))
lose.pack() #The if statement
deal = tk.Label(self, text="18", font=(18))
deal.pack(side="top", fill="y", pady=15, padx=270)
score = tk.Label(self, text="19", font=(18))
score.pack()
f = tk.Frame(self)
button1 = tk.Button(f,borderwidth=5, text="stand", font=(18),command =
lambda: win())#This is the button that i want to display the label
button1.grid(row=0,column=0)
button2 = tk.Button(f, text="Hit",borderwidth=5, font=(18))
button2.grid(row=0,column=1)
f.pack(side="bottom")
button3 = tk.Button(self, text="Quit", font=(18))
button3.pack(side="right", pady=50)
if __name__ == "__main__":
app = WINDOW()
app.geometry("800x400")
app.mainloop()
if score > deal: is comparing two tkinter label objects rather than the value of score and deal. Try getting the value of the labels and converting them to integers before doing the comparision.
if int(score['text']) > int(deal['text']):
To help with your other questions.
To chose a random number between 1 and 21, use the randint function contained inside python's random module (see code below). I've added a new randomise function which will be called after the page is created to randomly select a value for deal and score.
With the hit button, i've added a new function hit which will take the current score, and add another random value to it.
import tkinter as tk
from random import randint
k = 10
Q = 10
J = 10
A = 11 or 1
class WINDOW(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Memory") #sets the window title
container = tk.Frame(self)#Name of frame to refer to
container.pack(side="top", fill="both", expand=True)#size of window
container.grid_rowconfigure(0, weight=4)#size of window
container.grid_columnconfigure(0, weight=4)
self.frames = {}
for F in (MainMenu, tty):
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("MainMenu")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class MainMenu(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = 'white')
label = tk.Label(self, text="Memory",font=(15),
borderwidth=5, relief="solid")
label.pack(side="top", fill="y", pady=15, padx=270)
label.pack(fill="both")
button1 = tk.Button(self, text="Start", relief="solid",
borderwidth=5,width=30,
font=(17),command=lambda:
controller.show_frame("tty"))
button1.pack()
button3 = tk.Button(self,
text="Quit",relief="solid",borderwidth=4,width=30,font=(17),command = quit)
button3.place(x="420", y ="50")
button3.pack()
class tty(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.configure(background = "white")
self.deal = tk.Label(self, text="18", font=(18))
self.deal.pack(side="top", fill="y", pady=15, padx=270)
self.score = tk.Label(self, text="19", font=(18))
self.score.pack()
f = tk.Frame(self)
button1 = tk.Button(f,borderwidth=5, text="stand", font=(18),command = self.win)#This is the button that i want to display the label
button1.grid(row=0,column=0)
button2 = tk.Button(f, text="Hit",borderwidth=5, font=(18),command = self.hit)
button2.grid(row=0,column=1)
f.pack(side="bottom")
button3 = tk.Button(self, text="Quit", font=(18))
button3.pack(side="right", pady=50)
self.randomise()
def randomise(self):
self.deal['text'] = str(randint(1,21))
self.score['text'] = str(randint(1,21))
def hit(self):
current_score = int(self.score['text'])
new_score = current_score + randint(1,21)
self.score['text'] = str(new_score)
def win(self):
if int(self.score['text']) > int(self.deal['text']):
tts = tk.Label(self, text="win", font=(20))
tts.pack()
else:
lose = tk.Label(self, text="lose", font=(10))
lose.pack() #The if statement
if __name__ == "__main__":
app = WINDOW()
app.geometry("800x400")
app.mainloop()
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!