How can I remove items on a Tkinter window? - python

I am trying to clear the items on the window without closing the root window just the items visible.While everything is deleted Some of the labels are still left.I created a button "close" to remove the items.My code is as below;
from tkinter import*
root = Tk()
root.geometry("480x480")
# Node
myLabel1 = Label(root, text=f'Node')
myLabel1.grid(row=0, column=0)
rows = [] # show the input entry boxes
for i in range(6):
# name
entry = Entry(root, width=5, bd=5)
entry.grid(row=2+i, column=0)
# x
myLabel2 = Label(root, text=f'x{i}')
myLabel2.grid(row=2+i, column=1)
entry_x = Entry(root, width=5, bd=5)
entry_x.grid(row=2+i, column=2)
# y
myLabel3 = Label(root, text=f'y{i}')
myLabel3.grid(row=2+i, column=3)
entry_y = Entry(root, width=5, bd=5)
entry_y.grid(row=2+i, column=4)
# save current input row
rows.append((entry, entry_x, entry_y))
def close():
for name,ex,ey in rows:
name.destroy()
ex.destroy()
ey.destroy()
myLabel3.destroy()
myLabel2.destroy()
myLabel1.destroy()
myButton_close.destroy()
myButton_close = Button(root, text="close",padx = 10,pady = 10, command=close)
myButton_close.grid(row=8, column=6)
root.mainloop()
where could i be going wrong?

Create a Frame to hold the widgets and then you can destroy the frame to clear the window:
from tkinter import *
root = Tk()
root.geometry("480x480")
frame = Frame(root)
frame.pack(fill=BOTH, expand=1)
# Node
myLabel1 = Label(frame, text=f'Node')
myLabel1.grid(row=0, column=0)
rows = [] # store the input entry boxes
for i in range(6):
# name
entry = Entry(frame, width=5, bd=5)
entry.grid(row=2+i, column=0)
# x
myLabel2 = Label(frame, text=f'x{i}')
myLabel2.grid(row=2+i, column=1)
entry_x = Entry(frame, width=5, bd=5)
entry_x.grid(row=2+i, column=2)
# y
myLabel3 = Label(frame, text=f'y{i}')
myLabel3.grid(row=2+i, column=3)
entry_y = Entry(frame, width=5, bd=5)
entry_y.grid(row=2+i, column=4)
# save current input row
rows.append((entry, entry_x, entry_y))
def close():
frame.destroy()
myButton_close = Button(frame, text="close", padx=10, pady=10, command=close)
myButton_close.grid(row=8, column=6)
root.mainloop()
Grouping widgets into a frame make it easier to clear certain part of the window.

You create the labels in a loop but you are not saving any reference to the labels except for the last myLabel2/3. However you can ask a widget about its children, and then destroy them all:
def close():
for widget in root.winfo_children():
widget.destroy()

Related

how to update getting results from an entry box automatically?

I want to update getting results from an entry box in a way that when an integer enters, the equivalent rows of entry boxes appear below that. I have written the below code to make it work using a button. However, I want to make it happen automatically without a button as I entered the number, the rows update. I checked one way of doing that is using the after(). I placed after after() in the function and out of the function but it is not working.
from tkinter import *
root = Tk()
root.geometry("400x400")
n_para = IntVar()
label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)
entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)
def update():
for i in range(1, n_para.get()+1):
entryX = Entry(root)
entryX.grid(row=i+1, column=0)
entryY = Entry(root)
entryY.grid(row=i+1, column=1)
entryZ = Entry(root)
entryZ.grid(row=i+1, column=2)
root.after(100, update)
root.after(1, update)
button1 = Button(root, text="update", command=update)
button1.grid(row=1, column=0)
root.mainloop()
You should try using the <KeyRelease> event bind.
import tkinter as tk
def on_focus_out(event):
label.configure(text=inputtxt.get())
root = tk.Tk()
label = tk.Label(root)
label.pack()
inputtxt = tk.Entry()
inputtxt.pack()
root.bind("<KeyRelease>", on_focus_out)
root.mainloop()
This types the text entered in real-time.
Edited Code with OP's requirement:
from tkinter import *
root = Tk()
root.geometry("400x400")
n_para = IntVar()
label1 = Label(root, text="Numeric parameters")
label1.grid(row=0, column=0)
entry1 = Entry(root, textvariable=n_para)
entry1.grid(row=0, column=1)
def upd(event):
x = entry1.get()
if not x.isnumeric():
x = 0
for i in range(1, int(x)+1):
entryX = Entry(root)
entryX.grid(row=i+1, column=0)
entryY = Entry(root)
entryY.grid(row=i+1, column=1)
entryZ = Entry(root)
entryZ.grid(row=i+1, column=2)
# root.after(100, update)
root.bind("<KeyRelease>", upd)
# button1 = Button(root, text="update", command=update)
# button1.grid(row=1, column=0)
root.mainloop()

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.

How to align widgets in Tkinter to center

I am working on a simple counter app in tkinter. I rigged up some code looking at few tutorial on web. All the functions of a counter are set up. But when it comes to the designing of the app, I want the Count, the Count button, and the reset button to be aligned at the center.
The code is as below
from tkinter import Label, Button, Tk
from tkinter import font
window = Tk()
window.geometry('500x500')
window.title("Counter")
window.count = 0
def increment():
window.count += 1
lbl.configure(text=window.count)
def reset():
window.count = 0
lbl.configure(text=window.count)
lbl = Label(window, text="0", font=("Apple Braille", 60))
lbl.grid(column=0, row=0)
btn1 = Button(window, text="Count", command=increment)
btn1.grid(column=0, row=1)
btn2 = Button(window, text="Reset", command=reset)
btn2.grid(column=1, row=1)
btn1['font'] = btn2['font'] = font.Font(size=30)
window.mainloop()
A Screenshot of my counter app is here
Any help in this aspect will be appreciated.
Thanks,
It is easier to use pack() instead of grid() for your requirement.
lbl = Label(window, text="0", font=("Apple Braille", 60))
lbl.pack()
# frame for the two buttons
frame = Frame(window)
frame.pack()
btn1 = Button(frame, text="Count", command=increment)
btn1.grid(column=0, row=1)
btn2 = Button(frame, text="Reset", command=reset)
btn2.grid(column=1, row=1)
If you want to put at the center of the window:
# frame for the label and buttons
frame = Frame(window)
frame.place(relx=0.5, rely=0.5, anchor="c") # put at center of window
lbl = Label(frame, text="0", font=("Apple Braille", 60))
lbl.grid(row=0, column=0, columnspan=2)
btn1 = Button(frame, text="Count", command=increment)
btn1.grid(column=0, row=1)
btn2 = Button(frame, text="Reset", command=reset)
btn2.grid(column=1, row=1)

Add labels to the top of a tkinter grid?

The point of this is to press a button and have new rows appear but currently, titles appear above each new row that is added. Instead, I would like to have one row at the top of the grid with column titles. Is there a way to modify this code I already have? Later, I will be incorporating this into a larger tkinter GUI.
from tkinter import *
#------------------------------------
def addbox():
frame =Frame(root)
frame.pack()
#Item
Label(frame, text="Item").grid(row=0, column=0)
ent1 = Entry(frame, width=10)
ent1.grid(row=2, column=0)
#Day
Label(frame, text="Day").grid(row=0, column=1)
ent2 = Entry(frame, width=10)
ent2.grid(row=2, column=1)
#Code
ent3 = Entry(frame, width=10)
ent3.grid(row=2, column=2)
#Factor
ent4 = Entry(frame, width=10)
ent4.grid(row=2, column=3)
all_entries.append( (ent1, ent2, ent3, ent4) )
#Buttons.
showButton = Button(frame, text='Print', command=refresh)
addboxButton = Button(frame, text='Add Item', fg="Red", command=addbox)
#------------------------------------
def refresh():
for number, (ent1, ent2, ent3, ent4) in enumerate(all_entries):
print (number, ent1.get(), ent2.get(), ent3.get(),ent4.get())
#------------------------------------
all_entries = []
root = Tk()
addboxButton = Button(root, text='Add Instrument', fg="Red", command=addbox)
addboxButton.pack()
root.mainloop()
You can check the row count before you add the label:
if len(all_entries) < 1:
Label(frame, text="Item").grid(row=0, column=0)

How do I make entry boxes in a second window?

I have been trying to make an entry box for people to enter their names, as part of a "registration" for a mini-program that I am doing, but the result is that an entry box doesn't appear at all.
Here is the section of the code that is troubling me:
def win2(self):
# this is the child window
board = Toplevel()
board.title("Sign up")
board.focus_set()
board.grab_set()
userVar = StringVar()
userVar.set('Username')
square1Label = Label(board,textvariable=userVar)
square1Label.grid(row=0, column=7)
userEnt=Entry(self)
userEnt.grid(row=1, column=7)
s2Var = StringVar()
s2Var.set('First Name')
square2Label = Label(board,textvariable=s2Var)
square2Label.grid(row=1, column=7)
leaveButton = Button(board, text="Quit", command=board.destroy)
leaveButton.grid(row=1, column=1, sticky='nw')
board.wait_window(board)
And here is the coding in full, minus the importing of Tkinter and the mainloop:
class Application(Frame):
"""GUI Application for making Baakibook"""
def __init__(self, parent):
"""Initialize the frame"""
Frame.__init__(self, parent, bg="light blue")
self.win1()
# different windows
def win1(self):
# this is the main/root window
signupButton = Button(root, text="Sign up", command=self.win2)
signupButton.grid(row=9, column=7)
loginButton = Button(root, text="Log in", command=self.win3)
loginButton.grid(row=10, column=7)
leaveButton = Button(root, text="Quit", command=root.destroy)
leaveButton.grid(row=1, column=1, sticky='nw')
b1Var = StringVar()
b2Var = StringVar()
b1Var.set('b1')
b2Var.set('b2')
box1Label = Label(root,textvariable=b1Var,width=12)
box1Label.grid(row=3, column=2)
box2Label = Label(root,textvariable=b2Var,width=12)
box2Label.grid(row=3, column=3)
root.mainloop()
def win2(self):
# this is the child window
board = Toplevel()
board.title("Sign up")
board.focus_set()
board.grab_set()
userVar = StringVar()
userVar.set('Username')
square1Label = Label(board,textvariable=userVar)
square1Label.grid(row=0, column=7)
userEnt=Entry(self)
userEnt.grid(row=1, column=7)
s2Var = StringVar()
s2Var.set('First Name')
square2Label = Label(board,textvariable=s2Var)
square2Label.grid(row=1, column=7)
leaveButton = Button(board, text="Quit", command=board.destroy)
leaveButton.grid(row=1, column=1, sticky='nw')
board.wait_window(board)
def win3(self):
# this is the child window
board = Toplevel()
board.title("Login User")
board.focus_set()
board.grab_set()
s1Var = StringVar()
s2Var = StringVar()
s1Var.set("s1")
s2Var.set("s2")
square1Label = Label(board,textvariable=s1Var)
square1Label.grid(row=0, column=7)
square2Label = Label(board,textvariable=s2Var)
square2Label.grid(row=0, column=6)
leaveButton = Button(board, text="Quit", command=board.destroy)
leaveButton.grid(row=1, column=1, sticky='nw')
board.wait_window(board)
The first argument you use to create the widget is what parent you want it assigned to. So, this line:
userEnt=Entry(self)
userEnt.grid(row=1, column=7)
makes the Entry widget in the Frame that you created in __init__. If you want it to appear in the Toplevel, create it like the other widgets you made in that method, ie:
userEnt=Entry(board)
userEnt.grid(row=1, column=7)
Also, your grid in the Toplevel doesn't make sense right now and a couple of your widgets will appear stacked until you change it.

Categories