How do I enable .grid? - python

I wanted to position in the username and password such that it is next to each other. In order to achieve that I used the grid method but I keep getting an error that says:
_tkinter.TclError: cannot use geometry manager grid inside .!frame.!adminlogin.!frame which already has slaves managed by pack.
Is there a way I can let it use even grid?
import tkinter as tk
from tkinter import font as tkfont
import PIL.Image
from PIL import ImageTk
from tkinter import *
import tkinter.font as font
import sqlite3, hashlib
from datetime import date
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 ("1024x768")
container = tk.Frame(self)
container.pack(fill="both", side= 'top',expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, StudentLogin, AdminLogin):
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
frame = tk.Frame(self, width = 1024, height = 768, bg="teal")
frame.pack(fill="both", expand=True, side="top")
label = tk.Label(frame, text="WELCOME", font=controller.title_font)
label.pack(side="top", fill="x", pady=50)
button1 = tk.Button(frame, text="Admin Login",
command=lambda: controller.show_frame("AdminLogin"), width = 50, height=10, font=30, bg='powder blue')
button2 = tk.Button(frame, text="Student Login",
command=lambda: controller.show_frame("StudentLogin"), width=50, height=10, font=30, bg='powder blue')
button1.pack(pady=10)
button2.pack(pady=10)
class AdminLogin(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
frame = tk.Frame(self, width = 1024, height = 768, bg='teal')
frame.pack(fill="both", side ="top", expand=True)
label = tk.Label(frame, text="Enter username and password to login", font=controller.title_font)
label.pack(side="top", fill="x", pady=30, padx =10)
userLabel = tk.Label(frame, text = "Enter Username: ", font=50)
userLabel.pack(padx=10, pady=10)
userEntry = tk.Entry(frame)
userEntry.pack(padx=10, pady=10)
passwordL = tk.Label(frame, text = "Enter Password: ", font=50)
passwordL.pack(padx=10, pady=10)
passEntry = tk.Entry(frame, show="*")
passEntry.pack(padx=10, pady=10)
button = tk.Button(frame, text="Back",
command=lambda: controller.show_frame("StartPage"), bg='powder blue')
button.pack()
class StudentLogin(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
frame = tk.Frame(self, width = 1024, height = 768, bg='teal')
frame.pack(fill="both", side ="top", expand=True)
label = tk.Label(frame, text="Enter username and password to login", font=controller.title_font)
label.pack(side="top", fill="x", pady=30, padx =10)
button = tk.Button(frame, text="Back",
command=lambda: controller.show_frame("StartPage"), bg='powder blue')
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()

Unfortunately you cannot mix both the pack and grid methods. You have to only pick one, which you will use throughout that master. Pack is easier to use, but with grid you have more control over where your widgets are going to be displayed in the window. (I would have done this as a comment to your post, not an answer, but i do not have enough reputation to do so) I hope this helps :)

Related

How can I add an image as my background per page in Tkinter?

I want to know how can I add an image as my background per page in Tkinter, When you run the program, I want to have a background in the "Checkout" page and also when I click on the "Exit" page I want a different image background, How can I do that? Is it impossible? If yes, How can I add an image background on both pages?
Here's my code so far (don't mind if it's messy, it's just part of my codes):
import tkinter as tk
from tkinter import *
class IceCream(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)
self.frames = {}
for F in (Checkout, Exit):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Checkout)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class Checkout(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Checkout", font="times 40 bold")
label.pack(pady=30,padx=10)
label = tk.Label(self, text="Flavours", font="times 20 bold")
label.place(x=15, y=110)
self.sum_total=0
self.total_lbl=Label(self,font=("arial",17,'bold'),text=f'Total: {self.sum_total}')
self.total_lbl.place(x=250,y=440)
size=150
button1 = tk.Button(self, text="Start Again", font="times 15",
command=lambda: controller.show_frame(IceCream))
button1.place(x=20, y=440)
button2 = tk.Button(self, text="Exit", font="times 15",
command=lambda: controller.show_frame(Exit))
button2.place(x=480, y=440)
class Exit(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Thank you, " + '\n' + "Have a Good Day!!!", font="times 50 bold")
label.pack(anchor="c", ipady=180,ipadx=0)
app = IceCream()
app.mainloop()
you can try this
import tkinter as tk
root = tk.Tk()
bgimg = tk.PhotoImage(file="test.png") ## "test.png" is the image of background
bg = tk.Label(root, image=bgimg) ## remember that tkinter only supports .png .gif .bmp
bg.pack()
frame = tk.Frame(root) ## this is the container for your widgets
frame.place(x=0, y=0)
tk.Button(frame, text="Button").pack()
root.mainloop()

(python tkinter) pages with class, variable passed to other page, cant use as label : PY_VAR0

I had a problem with passing a variable from one page to the other, its works now, but if I want to use it on a label, it writes PA_VAR0. I read that ".get()" should be used in that case, but it still doesn't work that way. (with .get() it don't even passes the variable). I tried to set a new variable with tk.StringVar() function, but it still didn't work
import tkinter as tk
from tkinter import ttk
class example(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.shared_data = {
"variable": 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 (page1, page2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(page1)
def get_page(self, page_class):
return self.frames[page_class]
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = ttk.Label(self, text="first page")
label.grid(row=0, column=4, padx=10, pady=10)
button1 = ttk.Button(self, text="turn page",
command=lambda: self.pageturn())
button1.grid(row=3, column=1, padx=10, pady=10)
def pageturn(self):
self.controller.shared_data["variable"] = 'string i wanna pass'
print("variable set here: ", self.controller.shared_data["variable"])
self.controller.show_frame(page2)
class page2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = ttk.Label(self, text=self.controller.shared_data["variable"])
label.grid(row=0, column=4, padx=10, pady=10)
label = ttk.Label(self, text=self.controller.shared_data["variable"].get())
label.grid(row=1, column=4, padx=10, pady=10)
button3 = ttk.Button(self, text=self.controller.shared_data["variable"],
command=lambda: print(self.controller.shared_data["variable"]))
button3.grid(row=8, column=10, padx=10, pady=10)
button2 = ttk.Button(self, text="if fuction sees variable",
command=lambda: self.ifok())
button2.grid(row=9, column=10, padx=10, pady=10)
def ifok(self):
if self.controller.shared_data["variable"] == 'string i wanna pass':
print("ok")
app = example()
app.mainloop()
You overwrite self.controller.shared_data["variable"] by a string inside pageturn():
self.controller.shared_data["variable"] = 'string i wanna pass'
You should use .set() instead:
self.controller.shared_data["variable"].set('string i wanna pass')
Full updated code:
import tkinter as tk
from tkinter import ttk
class example(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.shared_data = {
"variable": 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 (page1, page2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(page1)
def get_page(self, page_class):
return self.frames[page_class]
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = ttk.Label(self, text="first page")
label.grid(row=0, column=4, padx=10, pady=10)
button1 = ttk.Button(self, text="turn page",
command=lambda: self.pageturn())
button1.grid(row=3, column=1, padx=10, pady=10)
def pageturn(self):
self.controller.shared_data["variable"].set('string i wanna pass') ### changed = to .set()
print("variable set here: ", self.controller.shared_data["variable"].get()) ### called .get()
self.controller.show_frame(page2)
class page2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = ttk.Label(self, textvariable=self.controller.shared_data["variable"]) ### changed text to textvariable
label.grid(row=0, column=4, padx=10, pady=10)
label = ttk.Label(self, text=self.controller.shared_data["variable"].get())
label.grid(row=1, column=4, padx=10, pady=10)
button3 = ttk.Button(self, textvariable=self.controller.shared_data["variable"], ### changed text to textvariable
command=lambda: print(self.controller.shared_data["variable"].get()))
button3.grid(row=8, column=10, padx=10, pady=10)
button2 = ttk.Button(self, text="if fuction sees variable",
command=lambda: self.ifok())
button2.grid(row=9, column=10, padx=10, pady=10)
def ifok(self):
if self.controller.shared_data["variable"].get() == 'string i wanna pass': ### called .get()
print("ok")
app = example()
app.mainloop()

Tkinter: Create an homepage look like

I'd like to create for my GUI an homepage like look, I've manege to arrive at this point, but now I'm little stuck. What I'd like to achieve is change the bottom_box when clicking the button that link to Page One or Page Two.
Thanks for your help!
EDIT I've worked on it a little bit and I've arrived at this point. When running my code now I get this error :
"Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python38-32\lib\tkinter_init_.py", line 1883, in call
return self.func(*args)
File "C:/folder/01.py", line 17, in
button1 = tk.Button(container, text="Go to Page One", command=lambda: controller.show_frame("PageOne"))
NameError: name 'controller' is not defined!
This is my edited code
import tkinter as tk
from PageOne import PageOne
from PageTwo import PageTwo
class MainApp(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
###MENU FRAME
left_frame = tk.Frame(root, borderwidth=1, bg= "white", relief="solid", highlightthickness=2)
left_frame.pack(side="left", expand=False, fill="y")
right_frame = tk.Frame(root, borderwidth=1, bg= "white", relief="solid", highlightthickness=2)
right_frame.pack(side="right", expand=True, fill="both")
container = tk.Frame(left_frame, borderwidth=1, bg= "white", relief="solid")
container.pack(expand=True, fill="both", padx=5, pady=5)
button1 = tk.Button(container, text="Go to Page One", command=lambda: controller.show_frame("PageOne"))
button1.pack(padx=20, pady=20)
button2 = tk.Button(container, text="Go to Page Two", command=lambda: controller.show_frame("PageTwo"))
button2.pack(padx=20, pady=20)
###TOP
top_box = tk.Frame(right_frame, borderwidth=1, bg= "white", relief="solid")
top_box.pack(expand=True, fill="both", padx=10, pady=10)
label_top = tk.Label(top_box, text="Title Logo", bg= "white")
label_top.pack()
###BOTTOM
bottom_box = tk.Frame(right_frame, borderwidth=1, bg= "green", relief="solid")
bottom_box.pack(expand=True, fill="both", padx=10, pady=10)
label_bott = tk.Label(bottom_box, text=" Logo", bg= "white")
self.frames = {}
for F in (PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=bottom_box, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
if __name__ == "__main__":
root = tk.Tk()
root.geometry("1200x650")
MainApp(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Page 1
import tkinter as tk
from tkinter import font as tkfont
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label_pg1 = tk.Label(self, text="page 1", bg= "white")
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
Page 2
import tkinter as tk
from tkinter import font as tkfont
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label_pg2 = tk.Label(self, text="page 2", bg= "white")
if __name__ == "__main__":
app = SampleApp()
app.mainloop()

Trying to code a password checker and generator using Tkinter

So far, I have the generator working but I can't get the tkinter to display the variable for the generated password, it only comes up in the console. Once I have the password checker working as well, I need that to be able to change variable as well, please help, here is a copy of my code
from tkinter import *
import tkinter as tk
from tkinter import font as tkfont
import random
import time
global strength
global gen
strength = 0;
gen = '[password will be here]';
global mypw
mypw = '';
def generate():
alphabet = "abcdefghijklmnopqrstuvwxyz"
pw_length = 8
mypw = ""
for i in range(pw_length):
next_index = random.randrange(len(alphabet))
mypw = mypw + alphabet[next_index]
# replace 1 or 2 characters with a number
for i in range(random.randrange(1,3)):
replace_index = random.randrange(len(mypw)//2)
mypw = mypw[0:replace_index] + str(random.randrange(10)) + mypw[replace_index+1:]
# replace 1 or 2 letters with an uppercase letter
for i in range(random.randrange(1,3)):
replace_index = random.randrange(len(mypw)//2,len(mypw))
mypw = mypw[0:replace_index] + mypw[replace_index].upper() + mypw[replace_index+1:]
print(mypw)
gen = mypw;
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
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):
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="Passowrd program", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Check your password strength",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Generate a new password",
command=lambda:[generate(),time.sleep(0.1),controller.show_frame("PageTwo")])
button3 = tk.Button(self, text="quit", command=close)
button1.pack()
button2.pack()
button3.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="Check your password", font=controller.title_font)
label1.pack(side="top", fill="x", pady=10)
entry = tk.Entry(self, bd =6)
button2 = tk.Button(self, text="Back",
command=lambda: controller.show_frame("StartPage"))
label2 = tk.Label(self, text="Strength:", font=controller.title_font)
label3 = tk.Label(self, text=strength, font=controller.title_font)
entry.pack()
button2.pack()
label2.pack()
label3.pack()
password = list(entry.get())
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
'''while 0 == 0:
gen = mypw;'''
var = StringVar()
var.set(gen)
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="Generate a password", font=controller.title_font)
label1.pack(side="top", fill="x", pady=10)
label2 = tk.Label(self, textvariable=var, font=controller.title_font)
button = tk.Button(self, text="Back",
command=lambda: controller.show_frame("StartPage"))
label2.pack()
button.pack()
def close():
messagebox.showinfo("BYE", "Thank you")
time.sleep(1)
app.destroy()
#def check_generate():
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
generate()
so, that's my code, I hope someone can help, it would be really useful, thanks
The problem is that you aren't updating the var StringVar that is used to display the generated password. Here's a version of your code which fixes that, but it is a little messy. There are a couple of other problems with your code, but I'll let you discover those. ;)
from tkinter import *
import tkinter as tk
from tkinter import font as tkfont
import random
import time
global strength
global gen
strength = 0
gen = '[password will be here]'
global mypw
mypw = ''
def generate(pwvar):
alphabet = "abcdefghijklmnopqrstuvwxyz"
pw_length = 8
mypw = ""
for i in range(pw_length):
next_index = random.randrange(len(alphabet))
mypw = mypw + alphabet[next_index]
# replace 1 or 2 characters with a number
for i in range(random.randrange(1,3)):
replace_index = random.randrange(len(mypw)//2)
mypw = mypw[0:replace_index] + str(random.randrange(10)) + mypw[replace_index+1:]
# replace 1 or 2 letters with an uppercase letter
for i in range(random.randrange(1,3)):
replace_index = random.randrange(len(mypw)//2,len(mypw))
mypw = mypw[0:replace_index] + mypw[replace_index].upper() + mypw[replace_index+1:]
print(mypw)
gen = mypw
pwvar.set(gen)
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
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):
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="Password program", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Check your password strength",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Generate a new password",
command=lambda:[generate(self.controller.frames['PageTwo'].var),time.sleep(0.1),controller.show_frame("PageTwo")])
button3 = tk.Button(self, text="quit", command=close)
button1.pack()
button2.pack()
button3.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="Check your password", font=controller.title_font)
label1.pack(side="top", fill="x", pady=10)
entry = tk.Entry(self, bd =6)
button2 = tk.Button(self, text="Back",
command=lambda: controller.show_frame("StartPage"))
label2 = tk.Label(self, text="Strength:", font=controller.title_font)
label3 = tk.Label(self, text=strength, font=controller.title_font)
entry.pack()
button2.pack()
label2.pack()
label3.pack()
password = list(entry.get())
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
self.var = StringVar()
self.var.set(gen)
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="Generate a password", font=controller.title_font)
label1.pack(side="top", fill="x", pady=10)
label2 = tk.Label(self, textvariable=self.var, font=controller.title_font)
button = tk.Button(self, text="Back",
command=lambda: controller.show_frame("StartPage"))
label2.pack()
button.pack()
def close():
messagebox.showinfo("BYE", "Thank you")
time.sleep(1)
app.destroy()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
generate()
Here's a slightly better way. Instead of having that dodgy list as the callback function in PageTwo we make a proper method, generate_password. Not only is it easier to read & to debug, by doing it this way we don't need to pass the password StringVar to generate, instead we can get generate to return the new password and then set the StringVar insidegenerate_password.
I've also gotten rid of that useless mypw global. I removed the messy from tkinter import *, and I added the tkinter.messagebox so that your close function will work.
import tkinter as tk
from tkinter import font as tkfont
import tkinter.messagebox as messagebox
import random
import time
global strength
global gen
strength = 0
gen = '[password will be here]'
def generate():
alphabet = "abcdefghijklmnopqrstuvwxyz"
pw_length = 8
mypw = ""
for i in range(pw_length):
next_index = random.randrange(len(alphabet))
mypw = mypw + alphabet[next_index]
# replace 1 or 2 characters with a number
for i in range(random.randrange(1,3)):
replace_index = random.randrange(len(mypw)//2)
mypw = mypw[0:replace_index] + str(random.randrange(10)) + mypw[replace_index+1:]
# replace 1 or 2 letters with an uppercase letter
for i in range(random.randrange(1,3)):
replace_index = random.randrange(len(mypw)//2,len(mypw))
mypw = mypw[0:replace_index] + mypw[replace_index].upper() + mypw[replace_index+1:]
print(mypw)
return mypw
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
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):
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="Password program", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Check your password strength",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Generate a new password",
command=self.generate_password)
button3 = tk.Button(self, text="quit", command=close)
button1.pack()
button2.pack()
button3.pack()
def generate_password(self):
password = generate()
password_var = self.controller.frames['PageTwo'].var
password_var.set(password)
time.sleep(0.1)
self.controller.show_frame("PageTwo")
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="Check your password", font=controller.title_font)
label1.pack(side="top", fill="x", pady=10)
entry = tk.Entry(self, bd =6)
button2 = tk.Button(self, text="Back",
command=lambda: controller.show_frame("StartPage"))
label2 = tk.Label(self, text="Strength:", font=controller.title_font)
label3 = tk.Label(self, text=strength, font=controller.title_font)
entry.pack()
button2.pack()
label2.pack()
label3.pack()
password = list(entry.get())
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
self.var = tk.StringVar()
self.var.set(gen)
tk.Frame.__init__(self, parent)
self.controller = controller
label1 = tk.Label(self, text="Generate a password", font=controller.title_font)
label1.pack(side="top", fill="x", pady=10)
label2 = tk.Label(self, textvariable=self.var, font=controller.title_font)
button = tk.Button(self, text="Back",
command=lambda: controller.show_frame("StartPage"))
label2.pack()
button.pack()
def close():
messagebox.showinfo("BYE", "Thank you")
time.sleep(1)
app.destroy()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
generate()

My buttons sit side by side in my Home window but they appear in the middle. How do I get them higher up?

I am having a similar issue with the Shop class too. My first button (Teapops) is where I want all my buttons on my Home window and Shop window to be (except for Back to Home) if I use:
button1.pack(side=TOP, anchor=NW, padx=10, pady=60, expand=NO)
button2.pack(side=TOP, anchor=NW, padx=30, pady=60, expand=NO)
button3.pack(side=TOP, anchor=NW, padx=60, pady=60, expand=NO)
But then all the others appear lower and lower and I don't have any idea why except maybe I have an issue with my frames?
If I use this,
button1.pack(side=LEFT, anchor=NW, fill=BOTH, expand=1)
button2.pack(side=LEFT, anchor=NW, fill=BOTH, expand=1)
button3.pack(side=LEFT, anchor=NW, fill=BOTH, expand=1)
then all my buttons appear side by side but in the middle of the screen again like on my Home screen:
Can someone please explain to me whats going on? I think there are some basics about Frames that I am not understanding. Please help!!!!
import Tkinter as tk
from Tkinter import *
TITLE_FONT = (“Helvetica”, 18, “bold”)
CREDITS_FONT = (“Helvetica”, 12, “bold”)
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)
self.frames = {}
for F in (Home, My_Plnts, Jrnl, Shop, Mail):
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(“Home”)
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
class Home(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
Home.configure(self, background=’#ade5ad’)
label = tk.Label(self, text=“Welcome Home, Maebert!”, background=’#ade5ad’, font=TITLE_FONT)
label.pack(side=“top”, fill=“x”, pady=10)
button1 = tk.Button(self, text=“My Plnts”,
command=lambda: controller.show_frame(“My_Plnts”))
button2 = tk.Button(self, text=“Jrnl”,
command=lambda: controller.show_frame(“Jrnl”))
button3 = tk.Button(self, text=“Shop”,
command=lambda: controller.show_frame(“Shop”))
button4 = tk.Button(self, text=“Mail”,
command=lambda: controller.show_frame(“Mail”))
button1.pack(side=LEFT, padx=60)
button2.pack(side=LEFT, padx=60)
button3.pack(side=LEFT, padx=60)
button4.pack(side=LEFT, padx=60)
class My_Plnts(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
My_Plnts.configure(self, background=’#ade5ad’)
label = tk.Label(self, text=“My Plnts”, background=’#ade5ad’, font=TITLE_FONT)
label.pack(side=“top”, anchor=NW, fill=“x”, pady=10)
button = tk.Button(self, text=“Back to Home”,
command=lambda: controller.show_frame(“Home”))
button.pack(side=“top”, anchor=NE)
class Jrnl(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
Jrnl.configure(self, background=’#ade5ad’)
label = tk.Label(self, text=“Jrnl”, background=’#ade5ad’, font=TITLE_FONT)
label.pack(side=“top”, fill=“x”, pady=10)
button = tk.Button(self, text=“Back to Home”,
command=lambda: controller.show_frame(“Home”))
button.pack(side=“top”, anchor=NE)
class Shop(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
Shop.configure(self, background=’#ade5ad’)
label = tk.Label(self, text=“Shop”, background=’#ade5ad’, font=TITLE_FONT)
label.pack(side=“top”, fill=“x”, pady=10)
label = tk.Label(self, text=“More at www.gfc.com”, background=’#ade5ad’, font=CREDITS_FONT)
label.pack(side=“bottom”, fill=“x”, pady=10)
button = tk.Button(self, text=“Back to Home”,
command=lambda: controller.show_frame(“Home”))
button1 = tk.Button(self, text=“Teapops”,
command=lambda: controller.show_frame(“Teapops”))
button2 = tk.Button(self, text=“Plants”,
command=lambda: controller.show_frame(“Plants”))
button3 = tk.Button(self, text=“Nail Polish”,
command=lambda: controller.show_frame(“Nail_Polish”))
button.pack(side=“top”, anchor=NE)
button1.pack(side=LEFT, anchor=NW, fill=BOTH, expand=1)
button2.pack(side=LEFT, anchor=NW, fill=BOTH, expand=1)
button3.pack(side=LEFT, anchor=NW, fill=BOTH, expand=1)
“”“
button1.pack(side=TOP, anchor=NW, padx=10, pady=60, expand=NO)
button2.pack(side=TOP, anchor=NW, padx=30, pady=60, expand=NO)
button3.pack(side=TOP, anchor=NW, padx=60, pady=60, expand=NO)
”“”
class Mail(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
Mail.configure(self, background=’#ade5ad’)
label = tk.Label(self, text=“Mail”, background=’#ade5ad’, font=TITLE_FONT)
label.pack(side=“top”, fill=“x”, pady=10)
button = tk.Button(self, text=“Back to Home”,
command=lambda: controller.show_frame(“Home”))
button.pack(side=“top”, anchor=NE)
if __name__ == “__main__”:
app = App()
app.minsize(300,300)
app.geometry(“800x800”)
app.mainloop()
I built the below program to demonstrate to you how the .pack() method works, please feel free to play around with the different options and see how each affects the output:
from tkinter import *
root = Tk()
top = Toplevel()
top.withdraw()
var1 = StringVar(root)
var1.set("top")
var2 = StringVar(root)
var2.set("none")
var4 = StringVar(root)
var4.set("center")
var3 = BooleanVar(root)
def command(top, var1, var3, var2):
top.destroy()
top = Toplevel()
top.geometry("500x500")
Label(top, text="Welcome home").pack()
Button(top, text="Button1").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
Button(top, text="Button2").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
Button(top, text="Button3").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
Button(top, text="Button4").pack(side=var1.get(), fill=var2.get(), expand=var3.get(), anchor=var4.get())
option1 = OptionMenu(root, var1, "top", "left", "bottom", "right")
check1 = Checkbutton(root, variable=var3, text="Expand?")
option2 = OptionMenu(root, var2, "none", "x", "y", "both")
option3 = OptionMenu(root, var4, "center", "n", "ne", "e", "se", "s", "sw", "w", "nw")
button1 = Button(root, text="Render", command=lambda:command(top, var1, var3, var2))
option1.pack()
check1.pack()
option2.pack()
option3.pack()
button1.pack()
root.mainloop()
This should show you how the different options affect the results of the .pack().
More to the point I believe the effect you are looking for can be achieved using .pack(side="left", expand="true", fill="x", anchor="n").

Categories