Button location(grid) in tkinter Python - python

Hey guys I have a problem and I have been searching for answers but I can't seem to solve my problem.
I want to move my "Enter" and "Quit" buttons more to the bottom of my window but I'm not sure I understand the grid function.
I made two frames inside my window and the buttons are in the bottom frame but I can't seem to get them lower with the row function.
I'm like just started with Python and have no experience with programming so this is my first project.(please don't laugh)
#import tkinder module
from tkinter import *
#make frame
root = Tk()
root.geometry("600x300")
top_frame = Frame(root)
bottom_frame = Frame(root)
top_frame.pack()
bottom_frame.pack()
#headline
headline = Label(top_frame, text="Welcome to PrintAssistant.", bg='blue', fg='white')
headline.config(font=('Courier', 27))
headline.grid(padx=10, pady=10)
Name = Label(bottom_frame, text="Name:", fg='blue')
Name.config(font=('Courier', 20))
Name.grid(row=1)
Password = Label(bottom_frame, text="Password:", fg='blue')
Password.config(font=('Courier', 20))
Password.grid(row=2)
Name_entry = Entry(bottom_frame)
Name_entry.grid(row=1, column=1)
Password_entry = Entry(bottom_frame)
Password_entry.grid(row=2, column=1)
#enter_button
enter_button = Button(bottom_frame, text="Enter", bg='blue', fg='white')
enter_button.config(height = 2, width = 15)
enter_button.grid(sticky = S)
#quit_button
quit_button = Button(bottom_frame, text="Quit", bg="blue", fg="white")
quit_button.config(height = 2, width = 15)
quit_button.grid(sticky = S)
root.mainloop()

Here is a quick and simple way to have your buttons sit at the bottom of your program.
First move enter_button and quit_button to the root window. A frame is not needed here.
then add root.rowconfigure() and apply a weight of 1 to the row the buttons are on. Configuring the row with a weight allows that row to expand and contract with the frame or window it is placed in. In this case we placed the buttons in root so we configured root. You could do the same to a frame but that is just adding another layer that is not needed for something simple like this.
Here is a section of code you can replace in your program and the result should be what you are looking for. Note I placed the buttons side by side but you can accomplish a top to bottom with the same method.
Edit:
I forgot to add the columnspan part. You also need to add a columnspan of the other frames so you can have your buttons placed centered when side by side. A columspan is used to tell the program how many columns that widget is going to be taking up. the same can be done with rows as well.
top_frame.grid(row = 0, column = 0, columnspan = 2)
bottom_frame.grid(row = 1, column = 0, columnspan = 2)
root.rowconfigure(2, weight = 1)
#enter_button
enter_button = Button(root, text="Enter", bg='blue', fg='white')
enter_button.config(height = 2, width = 15)
enter_button.grid(row = 2, column=0, sticky = 'se')
#quit_button
quit_button = Button(root, text="Quit", bg="blue", fg="white")
quit_button.config(height = 2, width = 15)
quit_button.grid(row = 2, column=1, sticky = 'sw')
If you want to keep the enter button on top of the quit button then you could do the following.
top_frame.grid(row = 0, column = 0) # remove columnspan or set it to 1
bottom_frame.grid(row = 1, column = 0)# remove columnspan or set it to 1
root.rowconfigure(2, weight = 1)
root.rowconfigure(3, weight = 0)
#enter_button
enter_button = Button(root, text="Enter", bg='blue', fg='white')
enter_button.config(height = 2, width = 15)
enter_button.grid(row = 2, column = 0, sticky = 's')
#quit_button
quit_button = Button(root, text="Quit", bg="blue", fg="white")
quit_button.config(height = 2, width = 15)
quit_button.grid(row = 3, column = 0, sticky = 's')
If you are just trying to place a little space between your entry fields and buttons you could use an spacer label. Something like this:
#empty row spacers
spacer1 = Label(bottom_frame, text = "")
spacer1.grid(row = 3)
spacer2= Label(bottom_frame, text = "")
spacer2.grid(row = 4)
#enter_button
enter_button = Button(bottom_frame, text="Enter", bg='blue', fg='white')
enter_button.config(height = 2, width = 15)
enter_button.grid(row = 5, column=1)
#quit_button
quit_button = Button(bottom_frame, text="Quit", bg="blue", fg="white")
quit_button.config(height = 2, width = 15)
quit_button.grid(row = 6, column=1)

I think you can do it by adding an extra Frame and set it to the bottom. After that put the Enter and Quit buttons on that frame. I have modified your code and you can try it.
#import tkinder module
from tkinter import *
#make frame
root = Tk()
root.geometry("600x300")
top_frame = Frame(root)
center_frame = Frame(root)
bottom_frame = Frame(root)
top_frame.pack()
center_frame.pack()
bottom_frame.pack(side = BOTTOM, fill = BOTH)
#headline
headline = Label(top_frame, text="Welcome to PrintAssistant.", bg='blue', fg='white')
headline.config(font=('Courier', 27))
headline.grid(padx=10, pady=10)
Name = Label(center_frame, text="Name:", fg='blue')
Name.config(font=('Courier', 20))
Name.grid(row=1)
Password = Label(center_frame, text="Password:", fg='blue')
Password.config(font=('Courier', 20))
Password.grid(row=2)
Name_entry = Entry(center_frame)
Name_entry.grid(row=1, column=1)
Password_entry = Entry(center_frame)
Password_entry.grid(row=2, column=1)
#enter_button
enter_button = Button(bottom_frame, text="Enter", bg='blue', fg='white')
enter_button.config(height = 2, width = 15)
enter_button.pack()
#quit_button
quit_button = Button(bottom_frame, text="Quit", bg="blue", fg="white")
quit_button.config(height = 2, width = 15)
quit_button.pack()
root.mainloop()
Please leave a comment if it worked for you :)

Related

How to know which button is pressed in tkinter? [duplicate]

This question already has answers here:
tkinter creating buttons in for loop passing command arguments
(3 answers)
Closed last year.
from tkinter import *
from Createwindow import *
button_name = ""
def click():
window = Tk()
window.geometry("600x500")
frame = Frame(window, bg = "#161853", width = 600, height = 500)
row_ = 0
column_ = 0
list = []
with open ("Passwords.txt", 'r') as data_file:
data = data_file.readlines()
for i in data:
names = i.split("|")
list.append(names[0])
for i in range(len(list)):
name = list[i]
button_ = Button(frame,text=name, font=("Helvetica", 12), width=16, bg="white", fg="black", command=create_window)
button_.grid(row=row_, column=column_, padx=(25, 0), pady=(25,0))
column_ += 1
if column_ == 3:
row_ += 1
column_ = 0
button_name = button_.cget('text')
frame.pack(fill="both", expand=True)
window.mainloop()
def create_window():
def fill_fields():
with open ("Passwords.txt", 'r') as data_file:
data = data_file.readlines()
for i in data:
names = i.split("|")
if names[0] == button_name:
Website_.insert(0, names[0])
Username_.insert(0, names[1])
Password_.insert(0, names[2])
def save_password():
if Website_.get() == "" or Username_.get() == "" or Password_.get() == "":
window = Tk()
Error_Message = Label(window, text = "Error! Please fill all the above fields.", bg="red", fg="white", font=("Arial", 16))
Error_Message.pack()
window.mainloop()
else:
with open("Passwords.txt" , 'a') as file:
file.write(Website_.get() + "|" + Username_.get() + "|" + Password_.get() + "\n")
window = Tk()
window.geometry("600x500")
window.configure(bg="#161853")
window.minsize(600, 500)
frame = Frame(window, bg="#161853")
frame.rowconfigure(2, weight=1)
frame.columnconfigure([0, 1, 2], weight=1)
Text = Label(frame, text="Save your password here", font=("Helvetica", 14), fg="white", bg="#161853")
Text.grid(row=0, column=1, pady=(0,25))
Website = Label(frame, text="Website:", font=("Helvetica", 14), fg="white", bg="#161853")
Website.grid(row=1, column=0, padx=(0, 15), pady=(0,20))
Website_ = Entry(frame, width=25)
Website_.grid(row=1, column=1, pady=(0, 20))
Username = Label(frame, text="Username/Email:", font=("Helvetica", 14), fg="white", bg="#161853")
Username.grid(row=2, column=0, padx=(0, 15), pady=(0, 20))
Username_ = Entry(frame, width=25)
Username_.grid(row=2, column=1, pady=(0, 20))
Password = Label(frame, text="Password:", font=("Helvetica", 14), fg="white", bg="#161853" )
Password.grid(row=3, column=0, padx=(0, 15), sticky="s")
Password_ = Entry(frame, width=25)
Password_.grid(row=3, column=1, pady=(0, 30), sticky="s")
Generate = Button(frame, text="Generate Password", font=("Helvetica", 12), width=16)
Generate.grid(row=3, column=2, sticky="s")
Save = Button(frame, text="Save Password", font=("Helvetica", 12), width=14, command=save_password)
Save.grid(row=4, column=1)
frame.place(relx=0.5, rely=0.5, anchor="center")
fill_fields()
window.mainloop()
In this piece of code basically I am creating a window where all the passwords saved in password.txt file will appear.
The code creates a button on the name of the website whose password is saved.
What I want to do is that when that button is clicked I want to get the text of the clicked button bcoz all the buttons are created automatically they have same name and the text of button is the one that is created in the last iteration.
You may pass the argument while adding click event in dynamic generated button.
for example below is your old code:
button_ = Button(frame,text = name , font = ("Helvetica", 12), width = 16, bg = "white" , fg = "black", command= create_window)
If you want to get the value of name when click on this button. Just do as like below:
button_ = Button(frame,text = name , font = ("Helvetica", 12), width = 16, bg = "white" , fg = "black", command= create_window(name))
Here i'm adding name argument in create_window function.
That i had already impletemented in my project and its working fine. Please try it and let me know if you will face any issue.
Please check below link for more details.
https://www.delftstack.com/howto/python-tkinter/how-to-pass-arguments-to-tkinter-button-command/

How can I import this entry answer into a text after

Okay so I have this sign up form and there is a part where you have to enter your name, I want that name answer to be taken to the page after.
import tkinter as tk
root = tk.Tk()
root.geometry("150x50+680+350")
def FormSubmission():
global button_start
button_start.place_forget()
l1.place_forget()
root.attributes("-fullscreen", True)
frame = tk.Frame(root)
tk.Label(frame, text="First Name:").grid(row=0)
name = entry1 = tk.Entry(frame) # I want the name written here to be taken from here to the welcome text.
entry1.grid(row=0, column=1)
tk.Label(frame, text="Last Name:").grid(row=1)
e2 = tk.Entry(frame)
e2.grid(row=1, column=1)
tk.Label(frame, text="Email:").grid(row=2)
e3 = tk.Entry(frame)
e3.grid(row=2, column=1)
tk.Label(frame, text="Date of Birth:").grid(row=3)
e4 = tk.Entry(frame)
e4.grid(row=3, column=1)
frame.pack(anchor='center', expand=True)
button_next = tk.Button(frame, text = "Next", height = 2, width = 7, command =lambda: MainPage(frame))
button_next.grid(row=4, column=1)
def MainPage(frame):
global FormSubmission
frame.pack_forget()
root.attributes("-fullscreen", True)
l1.place(x = 500, y = 10)
button_start.place_forget()
l1 = tk.Label(root, text="Welcome," , font=("Arial", 44)) #As you can see here in this line I want the entry 1 name here after welcome and the comma
button_start = tk.Button(root, text="Start", height=3, width=20, command = FormSubmission)
button_start.place(x = 0, y = 10)
button_exit = tk.Button(root, text="Exit", command=root.destroy)
button_exit.place(x=1506, y=0)
root.mainloop()
What I want to do is take the entry 1 answer and put it in the welcome text. There is an indicator on the lines I'm talking about.
Here is an example how to provide text from your widget entry1
in function FormSubmission():where you are defining your button you should pass the text you want to show in your label
button_next = tk.Button(frame, text = "Next", height = 2, width = 7, command =lambda: MainPage(frame, entry1.get()))
in funtion MainPage(frame):you should set text to your label:
def MainPage(frame, entry1):
global FormSubmission
frame.pack_forget()
root.attributes("-fullscreen", True)
l1.place(x = 500, y = 10)
button_start.place_forget()
l1.config(text="Welcome," + entry1) #<-------

How to navigate via pages in tkinter? [duplicate]

This question already has answers here:
Using buttons in Tkinter to navigate to different pages of the application?
(3 answers)
Closed 2 years ago.
So for my project when I click a button - the page must navigate to another. And when I do this each time it creates a different window (hence resulting in a lot of windows) or keeps stacking on top of each other
Currently I have a admin/student choice page. And if I click on the student page it will run the student log in function and this applies the same for the admin.
I want to keep the background of the windows consistent as well - but I am unable to do so and on top of that I have no clue on how to navigate via the pages - I have looked at a few videos but I did not really understand it.
contains 2 buttons admin and student which should navigate to different "windows" when clicked
def mainPage():
""""Starting Page - which navigates to the approporate login, when user logs it navigates back to this window"""
root = Tk()
root.geometry('1024x600')
load = PIL.Image.open('Image//book.jpg')
render = ImageTk.PhotoImage(load)
img =Label(root, image = render)
img.place(x=0, y=0)
my_font = font.Font(size = 15)
buttonFrame = Frame(root, width = 600, height=300, bg="grey")
buttonFrame.grid(row = 0, column = 0, padx= 10, pady=2, sticky="")
label = Label(buttonFrame, text = "Pick a Log-in", bg = "white", font=my_font).grid(row = 1, column=1, sticky="", padx=10, pady=10)
button = Button(buttonFrame, text = "Admin",command = adminLogin, width=30, height = 5, font=my_font).grid(row=2, column=1, sticky = "", padx= 10, pady=10)
button2 = Button(buttonFrame, text = "Student", command = studentLogin, width = 30, height=5, font=my_font).grid(row = 3, column=1, sticky="", padx = 10, pady=10)
root.mainloop()
def studentLogin():
root = Tk()
root.geometry('1024x600')
load = PIL.Image.open('Image//book.jpg')
render = ImageTk.PhotoImage(load)
img =Label(root, image = render)
img.place(x=0, y=0)
my_font = font.Font(size = 15)
buttonFrame = Frame(root, width = 600, height=600, bg="grey")
buttonFrame.grid(row = 0, column = 0, padx= 10, pady=2, sticky="")
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
label = Label (buttonFrame, text="Welcome", font=('Helvetica', 18, 'bold'), bg="white").grid(row = 1, column = 1,sticky="", padx=10, pady=10)
label = Label(buttonFrame, text="Username", font = my_font).grid(row=2, column=1, padx=10, pady=10)
usernameEntry = Entry(buttonFrame).grid(row=2, column=2, padx=10, pady=10)
root.mainloop()
Maybe try with PySimpleGUI :)
It has a convenient window.Hide() or window.UnHide() for these cases. Its also a great library for developping GUIs, good documentation, great support, and easy to pick up.
For tkinter, you could try with
root.withdraw()
and
root.update()
root.deiconify()

Tkinter scale widget labeling

I am new to Tkinter and try to make a little password generator. For the length of the password I want to implement a Scale widget. I have a weird problem with displaying the labeling of the widget, I do not understand why I get two different designs.
So this is a snippet from my main program:
root = Tk()
root.geometry("460x100")
root.resizable(0,0)
root.title("Password Generator")
pw_label = Label(root, text="Password").grid(row=0, column=0, pady=4, padx = 4)
length_label = Label(root, text="Length").grid(row=2, column=0, pady=4, padx = 4)
pw_input = Entry(root, width=50)
length_input = Scale(root, from_=8, to=50, orient=HORIZONTAL, length= 300)
length_input.set(30)
pw_input.grid(row = 0, column = 1, pady=4, padx = 4)
length_input.grid(row = 2, column = 1, pady=4, padx = 4)
Button(root, text='Quit', command=root.quit).grid(row=3, column=2, sticky=W, pady=4)
Button(root, text='Generate', command=rand_pw).grid(row=2, column=2, sticky=W, pady=4)
Button(root, text='Copy', command=copy).grid(row=0, column=2, sticky=W, pady=4)
root.mainloop()
As you can see, I have a blue slider and I have no scale under the Scale.
And here is another, minimal slider example:
from tkinter import *
root = Tk()
root.geometry("500x100")
length_label = Label(root, text="Length").grid(row=0, column=0, pady=4, padx = 4)
w2 = Scale(root, from_=0, to=50, tickinterval= 50, orient=HORIZONTAL, length=400)
w2.set(23)
w2.grid(row=0, column=1)
mainloop()
Can someone explain to me why I get two different stylings there? Both programs are in the same project folder in PyCharm. Also I start both examples in the same environment.
I think I just made a stupid mistake but I can not find it.
Refering to #Bryan Oakley´s answer I removed the from tkinter.ttk import * and afterwards I got the design as shown in my second screenshot.
Just deleted this one line although here is the working snippet.
from tkinter.ttk import *
root = Tk()
root.geometry("460x100")
root.resizable(0,0)
root.title("Password Generator")
pw_label = Label(root, text="Password").grid(row=0, column=0, pady=4, padx = 4)
length_label = Label(root, text="Length").grid(row=2, column=0, pady=4, padx = 4)
pw_input = Entry(root, width=50)
length_input = Scale(root, from_=8, to=50, orient=HORIZONTAL, length= 300)
length_input.set(30)
pw_input.grid(row = 0, column = 1, pady=4, padx = 4)
length_input.grid(row = 2, column = 1, pady=4, padx = 4)
Button(root, text='Quit', command=root.quit).grid(row=3, column=2, sticky=W, pady=4)
Button(root, text='Generate', command=rand_pw).grid(row=2, column=2, sticky=W, pady=4)
Button(root, text='Copy', command=copy).grid(row=0, column=2, sticky=W, pady=4)
root.mainloop()

Adjust the Grid and row and column setting in Tkinter height dose not match

I am using Grid manager to align the logframe at the right side in my program with my left side tracing method so that they can be at the same height. I already try to adjust the height of logframe, reset the position of the column but this also doesn't work,Any suggestion can improve my coding also can give me as well,regards.
This is the image:
Here is the code i use to set the logframe
def logDetails(self):
self.logframe = LabelFrame(self,text="Log Details",height= 450,width =390,padx=15)
self.logframe.grid_propagate(0)
self.logframe.grid_rowconfigure(0,weight =1)
self.logframe.grid_columnconfigure(0,weight=1)
xscrollbar = Scrollbar(self.logframe,orient = HORIZONTAL)
xscrollbar.grid(row=1, column=1, sticky=E+W,columnspan=2)
yscrollbar = Scrollbar(self.logframe)
yscrollbar.grid(row=0, column=3, sticky=N+S)
text = Text(self.logframe,width=50,height=60, wrap=NONE, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
text.grid(row=0, column=1, columnspan=2)
# attach listbox to scrollbar
xscrollbar.config(command=text.xview)
yscrollbar.config(command=text.yview)
button_1 = Button(self.logframe, text="View", command=printMessage)
button_1.grid(row=2,column= 1)
button_2 = Button(self.logframe, text="Export", command=printMessage)
button_2.grid(row=2,column= 2)
self.logframe.grid(row=0,column =1,rowspan=5)
Full coding it will be very helpful to solve this question:
from tkinter import *
class TracingInterface(Frame):
def __init__(self, root):
root.minsize(width=700, height=500)
root.maxsize(width=700, height=500)
Frame.__init__(self, root)
Grid.config(self)
self.TracingMethod()
self.logDetails()
self.otherFunctionInterface()
def TracingMethod(self):
self.traceMethodSelect = StringVar()
self.traceMethodSelect.set("LT")
self.radioframe = LabelFrame(self,text="Tracing Method",height= 120,width =300)
self.radioframe.grid(row= 0, column=0)
self.radioframe.grid_propagate(0)
self.radioframe.LT= Radiobutton(
self.radioframe, text="Live Tracing",
variable=self.traceMethodSelect, value="LT",
anchor=W).grid(row=1, column = 0, sticky = W,columnspan=2)
self.radioframe.SL= Radiobutton(
self.radioframe, text="Specific Location",
variable=self.traceMethodSelect, value="SL",
anchor=W).grid(row=2, column = 0, sticky = W,columnspan=2)
self.traceButton = Button(self.radioframe, text="Trace")
self.traceButton.grid(row =3, column =0, sticky = W)
self.cancelButton = Button(self.radioframe, text="Cancel")
self.cancelButton.grid(row =3, column =1, sticky = W)
self.configUAButton = Button(self.radioframe, text="Configuration")
self.configUAButton.grid(row =3, column =2, sticky = W)
self.configUAButton.config(width=15)
self.browseButton = Button(self.radioframe, text="Browse")
self.browseButton.grid(row =3, column =3, sticky = W)
location_ent =Entry(self.radioframe)
location_ent.grid(row =2, column = 2, sticky = W,columnspan=1)
def logDetails(self):
self.logframe = LabelFrame(self,text="Log Details",height= 450,width =390,padx=15)
self.logframe.grid_propagate(0)
self.logframe.grid_rowconfigure(0,weight =1)
self.logframe.grid_columnconfigure(0,weight=1)
xscrollbar = Scrollbar(self.logframe,orient = HORIZONTAL)
xscrollbar.grid(row=1, column=1, sticky=E+W,columnspan=2)
yscrollbar = Scrollbar(self.logframe)
yscrollbar.grid(row=0, column=3, sticky=N+S)
text = Text(self.logframe,width=50,height=60, wrap=NONE, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set)
text.grid(row=0, column=1, columnspan=2)
# attach listbox to scrollbar
xscrollbar.config(command=text.xview)
yscrollbar.config(command=text.yview)
button_1 = Button(self.logframe, text="View", command=printMessage)
button_1.grid(row=2,column= 1)
button_2 = Button(self.logframe, text="Export", command=printMessage)
button_2.grid(row=2,column= 2)
self.logframe.grid(row=0,column =1,rowspan=5)
def otherFunctionInterface(self):
self.otherFrame = LabelFrame(self,text="Other Function",height= 400,width =300)
self.otherFrame.grid(row=4, column=0)
self.otherFrame.grid_propagate(0)
OpenPreviousCaseFile = Button(self.otherFrame, text="Open previous Case File", command=printMessage,height = 4, width =25)
OpenPreviousCaseFile.grid(row=5,column= 0,pady=5)
OpenPreviousTracingResult = Button(self.otherFrame, text="Open previous Tracing Result ", command=printMessage,height = 4, width =25)
OpenPreviousTracingResult.grid(row=6,column= 0,pady=5)
OpenMenualbtn = Button(self.otherFrame, text="User Manual", command=printMessage,height =4, width =25)
OpenMenualbtn.grid(row=7,column= 0,pady=5)
AboutBtn = Button(self.otherFrame, text="About", command=printMessage,height = 4, width =25)
AboutBtn.grid(row=8,column= 0,pady=5)
def printMessage():
print("Wow this actually worked!")
root = Tk()
root.title("Windows User Activity History Tracing and Analysing System")
tif= TracingInterface(root)
root.mainloop()

Categories