Is it possible to overwrite an entry field with label in tkinter? - python

I have a simple label and entry field that would:
1) Create a static label and clear the entry field after confirmation button click
2) Clear static label after reset button click
Is there any way to overwrite the entry field with a static label of the user input on the confirmation click instead of creating a new static label? And overwriting the static label with an empty entry field on the reset click?
Thank you for the help in advance.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
set_cname.destroy()
cbtn['state'] = NORMAL
def confirm():
global set_cname
text1="Customer Name: " + entry1.get()
set_cname = Label(frame1, text=text1)
set_cname.grid(row=3, column=0, columnspan=1)
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ").grid(padx=5, pady=5, columnspan=2, sticky=W)
entry1 = Entry(frame1)
entry1.grid(row=0, column=2, padx=5)
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=4, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=4, padx=5, pady=5)
root.mainloop()

You can replace the Entry with a Label by first creating both and then using pack() to switch between them. The trick is to not let their different sizes affect the application layout, which can be accomplished by disabling size propagation.
In my example I create a new frame (entry_frame) with a fixed size and then disable size propagation (.pack_propagate(False)). Then I use this new frame to contain the Entry/Label. Im giving the entry_frame the bg color khaki to let you see exactly where it is.
I fiddled a bit with the column numbers also.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
text_label.pack_forget()
entry1.pack()
cbtn['state'] = NORMAL
def confirm():
global set_cname
entry1.pack_forget()
text_label.config(text=entry1.get())
text_label.pack(side='left')
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ")
cname.grid(row=0, column=0, padx=5, pady=5, sticky=W)
entry_frame = Frame(frame1, width=130, height=20, bg='khaki')
entry_frame.grid(row=0, column=1, padx=5, pady=5, sticky='nsew')
entry_frame.pack_propagate(False) # Disable size propagation
entry1 = Entry(entry_frame) # Customer name entry
entry1.pack()
text_label = Label(entry_frame) # Label to hold customer name
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=2, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=2, padx=5, pady=5)
root.mainloop()
Be aware that this solution will be sensitive to font size changes.

Related

Aligning entries/buttons with tkinter

I've been trying to align the entries and buttons on this password manager I built for a while now but haven't been able to find a solution that works.
I tried changing the width, columnspan, and coordinates but it doesn't seem to work.
I want the password entry to be aligned just like the other two but with a lower width so that the generate button does not go over. I also want the add button to be aligned equally with the row and column.
window = Tk()
window.title("Password Manager")
window.config(padx=50, pady=50)
canvas = Canvas(width=200, height=200)
my_pass_img = PhotoImage(file="logo.png")
canvas.create_image(100, 100, image=my_pass_img)
canvas.grid(column=1, row=0)
web_label = Label(text="Website:", fg="black")
web_label.grid(row=1, column=0)
user_label = Label(text="Email/Username:", fg="black")
user_label.grid(row=2, column=0)
pass_label = Label(text="Password:", fg="black")
pass_label.grid(row=3, column=0)
web_entry = Entry(width=35)
web_entry.grid(row=1, column=1, columnspan=2)
web_entry.focus()
user_entry = Entry(width=35)
user_entry.grid(row=2, column=1, columnspan=2)
user_entry.insert(0, "-#gmail.com")
pass_entry = Entry(width=30)
pass_entry.grid(row=3, column=1)
generate_button = Button(text="Generate Password", fg="black", command=generate_password)
generate_button.grid(row=3, column=2)
add_button = Button(width=36, text="Add", fg="black", command=save)
add_button.grid(row=4, column=1, columnspan=2)
window.mainloop()
Grid
When using grid to setup your widgets, the entire window is divided into individual cells based on the number of columns and rows you've specified. Although you can control the individual sizes of widgets, the overall size it can take will be limited by your choice of column- and rowwidth, as well as column- and rowspan.
Sticky
You can use the sticky attribute in grid to set the side of the column you want your widgets to 'stick' to.
The stickiness is set by choosing one of the 8 directions on a compass:
N (north): stick to top of cell
S (south): bottom
E (east): right
W (west): left
NW, NE, SW, SE: top-left, top-right, bottom-left, bottom-right corners respectively.
There are also two bonus stickiness options:
NS: stretch your widget from top to bottom of the sell, but keep it centered horizontally
EW: stretch from left to right of the cell, but centered vertically.
Padding
To increase legibility, you can add padding above and below, and to the sides, of your widgets using the padx and pady attributes (measured in pixels).
So if you set stickyness to "W" with a horizontal padding padx=5, the widget position is offset from the cell boundary by 5 pixels.
Combining it in your example
To align the entries, set their sticky attribute to "W", or tk.W, to algin on left side of cell.
If you want to align labels on the right set sticky="E".
You can reduce the columnspan too of the entries, if you don't need them to be extra large. The resulting changes to grid are thus:
canvas.grid(column=1, row=0)
# Label widgets: set sticky to 'East'
web_label.grid(row=1, column=0, sticky='E')
user_label.grid(row=2, column=0, sticky='E')
pass_label.grid(row=3, column=0, sticky='E')
# Entry widgets
web_entry.grid(row=1, column=1, columnspan=1, sticky='WE')
user_entry.grid(row=2, column=1, columnspan=1, sticky=tk.EW) # Note flag is available as tkinter attribute
# Password entry: align on left-hand side
pass_entry.grid(row=3, column=1, sticky='W')
# Align button to right side of 3rd column
generate_button.grid(row=3, column=2,sticky='E')
# Can either align in middle column...
add_button.grid(row=4, column=1, columnspan=1, sticky="WE")
#... or in middle of page
add_button.grid(row=4, column=0, columnspan=3, sticky="WE")
Bonus
Apply padding (or sticky) to all widgets in a frame or window:
for child in window.winfo_children():
child.grid_configure(padx=3, pady=3)
# child.grid_configure(sticky='W')
You can use sticky option to put the widget in a grid cell at "n" (north), "s" (south), "e" (east) and "w" (west). If not specify, it is by default is "" which will put the widget at the center of the cell.
For your case, add sticky="w" to all the labels and entries, and sticky="e" to the "Add" button:
from tkinter import *
def generate_password():
pass
def save():
pass
window = Tk()
window.title("Password Manager")
window.config(padx=50, pady=50)
canvas = Canvas(window, width=200, height=200)
my_pass_img = PhotoImage(file="logo.png")
canvas.create_image(100, 100, image=my_pass_img)
canvas.grid(column=1, row=0)
web_label = Label(window, text="Website:", fg="black")
web_label.grid(row=1, column=0, sticky="w")
user_label = Label(window, text="Email/Username:", fg="black")
user_label.grid(row=2, column=0, sticky="w")
pass_label = Label(window, text="Password:", fg="black")
pass_label.grid(row=3, column=0, sticky="w")
web_entry = Entry(window, width=35)
web_entry.grid(row=1, column=1, columnspan=2, sticky="w")
web_entry.focus()
user_entry = Entry(window, width=35)
user_entry.grid(row=2, column=1, columnspan=2, sticky="w")
user_entry.insert(0, "-#gmail.com")
pass_entry = Entry(window, width=30)
pass_entry.grid(row=3, column=1, sticky="w")
generate_button = Button(window, text="Generate Password", fg="black", command=generate_password)
generate_button.grid(row=3, column=2)
add_button = Button(window, width=36, text="Add", fg="black", command=save)
add_button.grid(row=4, column=1, columnspan=2, sticky="e")
window.mainloop()
Result:
You can play around with different values or combinations of them of the sticky option to see the different effects.
Note also that it is better to specify the parent of those widgets.

Why i can't fix the boxes alignment in Gridview on windows

there are some space between the result as you can see in the image that password entry and generate password aren't aligning together
*Result image
from tkinter import
window = Tk()
window.title("Password Manager")
window.config(padx=20, pady=20)
canvas = Canvas(width=200, height=200, highlightthickness=0)
password_image = PhotoImage(file="logo.png")
image = canvas.create_image(100, 100, image=password_image)
canvas.itemconfig(image)
canvas.grid(row=0, column=1)
website_label = Label(text="Website")
website_label.grid(row=1, column=0)
Email_username_label = Label(text="Email/Username")
Email_username_label.grid(row=2, column=0)
password_label = Label(text="Password")
password_label.grid(row=3, column=0)
website_input = Entry(width=35)
website_input.grid(row=1, column=1, columnspan=2)
Email_username_input = Entry(width=35)
Email_username_input.grid(row=2,column=1, columnspan=2)
password = Entry(width=21)
password.grid(row=3, column=1)
generate_button = Button(text="Generate Password")
generate_button.grid(row=3, column=2)
add_password_button = Button(text="Add", width=36)
add_password_button.grid(row=4, column=1, columnspan=2)
window.mainloop()
You can see that there is some space in password entry and generate password how to fix it
As noted in the comments, using the grid method allows you to just add sticky to align elements. In this case, I've removed all the width options in your entries and buttons with stick='EW' to expand East and West, or to the maximum left and right of the column the widget is in.
from tkinter import *
window = Tk()
window.title("Password Manager")
window.config(padx=20, pady=20)
# Canvas
canvas = Canvas(width=200, height=200, highlightthickness=0)
password_image = PhotoImage(file="logo.png")
image = canvas.create_image(100, 100, image=password_image)
canvas.itemconfig(image)
canvas.grid(row=0, column=1)
# Labels
website_label = Label(text="Website")
website_label.grid(row=1, column=0)
Email_username_label = Label(text="Email/Username")
Email_username_label.grid(row=2, column=0)
password_label = Label(text="Password")
password_label.grid(row=3, column=0)
# Entries
website_input = Entry()
website_input.grid(row=1, column=1, columnspan=2, sticky='EW') # sticky
Email_username_input = Entry()
Email_username_input.grid(row=2, column=1, columnspan=2, sticky='EW') # sticky
password = Entry()
password.grid(row=3, column=1, sticky='EW') # sticky
# Buttons
generate_button = Button(text="Generate Password")
generate_button.grid(row=3, column=2)
add_password_button = Button(text="Add")
add_password_button.grid(row=4, column=1, columnspan=2, sticky='EW') # sticky
window.mainloop()
You may also want to consider reading up on column and row weights using columnconfigure and rowconfigure if you want your GUI to resize dynamically.

Adjusting location of Entry in Tkinter

I am trying to get the text username and password in the below Tkinter to be next to the Entry, I have tried to play with the columns but it didn't fix it. I was previously using pack() but switched to grid() to be more in control of the location of the labels.
Here is the code:
root = Tk()
root.title("Bookmark Search")
root.resizable(0,0)
greeting= Label(root, text="Hi, This is a Trial to see how the label works !")
help=Label(root, text=" How can I help you today?")
greeting.grid(row = 0, column= 1, pady=5, padx=200)
help.grid(row = 1, column= 1,pady=5)
e = Entry(root, width=50)
e.grid(row=2, column = 1,rowspan=2, pady=15)
mySubmit = Label(root)
-------several lines of unrelated code-------
mySubmit.bind("<Button-1>", open_url)
root.bind('<Return>', myClick)
myButton= Button(root, text="Submit", command=myClick)
myButton.grid(row=4, column = 1,rowspan=2, pady=10)
# username
username_label = Label(root, text="Username:")
username_label.grid(column=0, row=8, padx=5, pady=5)
username_entry = Entry(root)
username_entry.grid(column=1, row=8, padx=5, pady=5)
# password
password_label = Label(root, text="Password:")
password_label.grid(column=0, row=9, padx=5, pady=5)
password_entry = Entry(root)
password_entry.grid(column=1, row=9, padx=5, pady=5)
# login button
login_button = Button(root, text="Login")
login_button.grid(column=1, row=10,padx=5, pady=5)
root.mainloop()
Here is a print screen of the current output:
Here is the required output:
You can put Labels and Buttons in Frame and then Frame put in main window.
import tkinter as tk # PEP8: `import *` is not preferred
# --- functions --- (PEP8: lower_case_names)
def open_url():
pass
def my_click():
pass
# --- main ---
root = tk.Tk()
root.title("Bookmark Search")
root.resizable(0,0)
greeting = tk.Label(root, text="Hi, This is a Trial to see how the label works !")
help = tk.Label(root, text=" How can I help you today?")
greeting.grid(row=0, column=1, pady=5, padx=200)
help.grid(row=1, column=1, pady=5)
e = tk.Entry(root, width=50)
e.grid(row=2, column=1, pady=15)
my_submit = tk.Label(root, text='LABEL')
my_submit.grid(row=3, column=1, pady=10)
my_submit.bind("<Button-1>", open_url)
root.bind('<Return>', my_click)
my_button = tk.Button(root, text="Submit", command=my_click)
my_button.grid(row=4, column=1, pady=10)
# - start Frame - to group widgets -
frame = tk.Frame(root)
frame.grid(column=1, row=5)
# username
username_label = tk.Label(frame, text="Username:")
username_label.grid(column=0, row=8, padx=5, pady=5)
username_entry = tk.Entry(frame)
username_entry.grid(column=1, row=8, padx=5, pady=5)
# password
password_label = tk.Label(frame, text="Password:")
password_label.grid(column=0, row=9, padx=5, pady=5)
password_entry = tk.Entry(frame)
password_entry.grid(column=1, row=9, padx=5, pady=5)
# - end Frame -
# login button
login_button = tk.Button(root, text="Login")
login_button.grid(column=1, row=10, padx=5, pady=5)
root.mainloop()
PEP 8 -- Style Guide for Python Code

How to get only a corresponding entry box regardless of how many times I change radiobutton?

from tkinter import *
win=Tk()
var = StringVar()
l = Label(win, bg='white', width=15)
l.grid(row=17,column=1,padx=10, pady=10, sticky='w')
def print1_selection():
if var.get()=="Number":
lab1= Label(win, text="Enter a number").grid(row=4, column=0)
ent1=Entry(win).grid(row=4, column=1)
l.config(text='you have selected ' + var.get())
elif var.get()=="Alphabet":
lab21= Label(win, text="Enter an alphabet").grid(row=5, column=0)
ent21=Entry(win).grid(row=5, column=1)
l.config(text='you have selected ' + var.get())
lbl4=Label(win, text="Select One", bg="crimson", fg="white", font=("times new
roman",15,"bold")).grid(row=1, column=0, padx=10, pady=10, sticky='w')
r1 = Radiobutton(win, text='Number',variable=var, value='Number', command=print1_selection, width=22)
r1.grid(row=2,column=0,padx=10, pady=10)
r2 = Radiobutton(win, text='Alphabet', variable=var, value='Alphabet', command=print1_selection, width=22)
r2.grid(row=2,column=1,padx=10, pady=10)
win.mainloop()
In this code I want that when I select radiobutton number, only enter a number should appear and same for the other.
But the problem is that when I select number after selecting alphabet, it shows both. I need only the selected one and eliminate the other instantly.
This is how I would approach this issue:
from tkinter import Tk, StringVar, Label, Frame, Entry, Radiobutton
def print1_selection():
for widget in entry_frame.winfo_children():
widget.destroy()
value = var.get()
lbl.config(text='You have selected ' + value)
if value == "Number":
Label(entry_frame, text="Enter a number").grid(row=0, column=0)
Entry(entry_frame).grid(row=0, column=1)
elif value == "Alphabet":
Label(entry_frame, text="Enter an alphabet").grid(row=0, column=0)
Entry(entry_frame).grid(row=0, column=1)
win = Tk()
var = StringVar(value=0)
entry_frame = Frame(win)
entry_frame.grid(row=2, column=0, columnspan=2)
lbl = Label(win, bg='white', width=20)
lbl.grid(row=3, column=0, columnspan=2, padx=10, pady=10, sticky='w')
Label(win, text="Select One", bg="crimson", fg="white", font=("times new roman", 15, "bold")).grid(row=0, column=0, padx=10, pady=10, sticky='w')
Radiobutton(win, text='Number', variable=var, value='Number', command=print1_selection, width=22).grid(row=1, column=0, padx=10, pady=10)
Radiobutton(win, text='Alphabet', variable=var, value='Alphabet', command=print1_selection, width=22).grid(row=1, column=1, padx=10, pady=10)
win.mainloop()
As You can see if You don't plan on using the widgets instance anywhere You don't have to assign it to a variable. Also no need to configure label in both statements since that will be done anyways so just do it at the beginning, also rows start from 0 too. Frames help with organizing widgets. Also if You want neither of the radiobuttons selected set the variable to 0.

Python Tkinter grid spacing of widgets and LablelFrames not right

I am designing a simple GUI in Python 2.7 Tkinter, but I can't get things to spread out as I want them. I have managed to get my various widgets roughly where I want them, however I can't seem to force spacing out and things are a little bunched up.
I have also tried to draw 3 LabelFrames to separate the window out, but widgets seem to fall over the LabelFrames. I am wondering how I can space this out a little better. The grid system seems to allow things to bunch up and ignores blank rows and columns as far as I can see.
from Tkinter import *
import Tkinter, Tkconstants, tkFileDialog, tkMessageBox
class FileZap():
def __init__(self, root):
root.title("TestGUI")
root.geometry("860x450")
self.topFrame = LabelFrame(root, text="Top Area")
self.topFrame.grid(row=1, column=1, rowspan=6, columnspan=7, padx=5, pady = 5, sticky="NSEW")
self.listbox1 = Listbox(root, width=50, selectmode="multiple")
self.listbox1.grid(row=3, column=2)
self.scrollbar = Scrollbar(orient=VERTICAL, command=self.listbox1.yview)
self.listbox1.config(yscrollcommand=self.scrollbar.set)
self.scrollbar.grid(row=3, column=3, sticky="ns")
self.listbox2 = Listbox(root, width=50)
self.listbox2.grid(row=3, column=4)
self.selectLabel = Label(root, text="Select a folder: ")
self.selectLabel.grid(row=3, column=1)
self.user1 = Entry(root, width="50")
self.user1.grid(row=2, column=2)
self.browse = Button(root, text="Browse")
self.browse.grid(row=2, column=3)
self.addItems = Button(root, text="Add to Selection")
self.addItems.grid(row=4, column=2)
self.clearItems = Button(root, text="Clear Selection")
self.clearItems.grid(row=4, column=4)
self.leftFrame = LabelFrame(root, text="Left Area")
self.leftFrame.grid(row=5, column=1, rowspan=6, columnspan=3, padx=5, pady = 5, sticky="NSEW")
self.replaceInLable = Label(root, text="String to replace: ")
self.replaceOutLable = Label(root, text="New string: ")
self.replaceInLable.grid(row=7, column=1)
self.replaceOutLable.grid(row=7, column=2)
self.replaceIn = Entry(root, width="20")
self.replaceOut = Entry(root, width="20")
self.replaceIn.grid(row=8, column=1)
self.replaceOut.grid(row=8, column=2)
self.replace = Button(root, text="Replace")
self.replace.grid(row=8,column=3)
self.rightFrame = LabelFrame(root, text="Right Area")
self.rightFrame.grid(row=5, column=4, rowspan=6, columnspan=3, padx=5, pady = 5, sticky="NSEW")
self.quit = Button(root, text="Exit", command=root.quit)
self.quit.grid(row=9, column=6)
root = Tkinter.Tk()
file_zap = FileZap(root)
root.mainloop()
I have tried various alterations but can't nail it! Any help would be much appreciated.
First, the columns / row adapt to there content so an empty one as a zero height/width. If you want to put space between your widgets use the padx and pady options in the .grid method. They can take either one number which will give the padding on both sides or a couple of numbers giving the padding on each side.
Secondly, if you want your widgets to be inside a LabelFrame, you need to create them with this LabelFrame as master instead of the main window.
from Tkinter import LabelFrame, Tk, Button, Label
root = Tk()
# make row 0 resize with the window
root.rowconfigure(0, weight=1)
# make column 0 and 1 resize with the window
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
# create LabelFrames
top_frame = LabelFrame(root, text="top")
left_frame = LabelFrame(root, text="left")
right_frame = LabelFrame(root, text="right")
top_frame.grid(row=0, column=0, columnspan=2, padx=10, pady=(10,4), sticky="nsew")
left_frame.grid(row=1, column=0, padx=(10,4), pady=4, sticky="nsew")
right_frame.grid(row=1, column=1, padx=(4,10), pady=4, sticky="nsew")
#create widgets inside top_frame
Label(top_frame, text="I'm inside top_frame").pack()
Button(top_frame, text="Top").pack()
#create widgets inside left_frame
Label(left_frame, text="I'm inside left_frame").pack()
Button(left_frame, text="Left").pack()
#create widgets inside top_frame
Label(right_frame, text="I'm inside right_frame").pack()
Button(right_frame, text="Right").pack()
Button(root, text="Quit", command=root.destroy).grid(row=2, column=0,
columnspan=2, pady=10)
root.mainloop()

Categories