Tkinter python: issue with clearing out the widget - python

Someone please help me figure this out.
I have the following problem in Tkinter Python. The problem is that the text is overlaying with the previous text. and/or is copying below that.
I've tried to use label.config(root).pack() instead of Label(root, text="").pack()
This kinda solves the problem it starts to write over the previous text but there are 2 problems with this.
1: the text old text/Entrys all still there, it just overlays.
2: this only works with label.config, and I would also like this to work with buttons and Entrys(textbox)
I've also tried .pack_forget() and .destroy() but unfortunately it did nothing.
CODE
from tkinter import *
import pickle
import time
import os
def new_profile():
global Var1, Var2
var1 = StringVar()
var2 = StringVar()
Label(root, text="Create a new profile").pack()
Label(root, text="User Name").pack()
Entry(root, textvariable=var1).pack()
Label(root, text="Password").pack()
Entry(root, textvariable=var2).pack()
Button(root, text="Create", command=create_profile).pack()
Var1, Var2 = var1, var2
return
def create_profile():
text1 = Var1.get()
text2 = Var2.get()
print(text1)
dict = {}
dict['Name'] = text1
dict['Password'] = text2
pickle.dump(dict, open("test.txt", "wb"))
dict1 = pickle.load(open("test.txt", "rb"))
if dict1['Name'] == text1 and dict1['Password'] == text2:
Label(root, text="").pack()
Label(root, text="Profile creation successful", ).pack()
Label(root, text="Name:" + " " + text1).pack()
Label(root, text="Password:" + " " + text2).pack()
else:
Label(root, text="Something went wrong while creating your profile.", ).pack()
return
def load_profile():
select = "Load profile.."
label.config(text=select)
return
root = Tk()
root.geometry("500x400+300+300")
root.title("client")
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New Profile", command=new_profile)
filemenu.add_command(label="Load Profile", command=load_profile)
menubar.add_cascade(label="Profile Options", menu=filemenu)
root.config(menu=menubar)
label = Label(root)
label.pack()
root.mainloop()

create a array such as
on_screen = []
at the start then name your widgets and and add them to the array
password_label = Label(root, text="Password").pack()
password = Entry(root, textvariable=var2).pack()
on_screen.append(password)
on_screen.append(password_label)
then use a for loop to destroy all the widgets in the array
for w in on_screen:
w.destroy()

Related

Values not stored in Tkinter Variables

In my code, I have tried to get the user input through text fields, store them in variables and finally print them in a tabular form.
The problem I am facing is that none of the values I enter through the text fields get displayed; when I try printing the variables, they come up empty.
Here's part of my code:
# SPASC
from tkinter import *
import tkinter as tk
import tkinter.ttk as tktrv
root = tk.Tk()
root.title("SPASC")
root.geometry("410x400")
lb1 = Label(root, text="SPASC \n Welcomes You !!!", fg="red", bg="sky blue"
, font=('Arial Black', 20), width=22, anchor=CENTER)
lb2 = Label(root, text="What would you like to compare?",
font=('Arial', 18), anchor=CENTER)
space1 = Label(root, text="\n\n")
lb1.grid(row=0)
lb2.grid(row=5)
space1.grid(row=1)
hpw, mil = StringVar(), StringVar()
def bt_cars():
w1 = Toplevel()
w1.title("Choose Features")
w1.geometry("430x200")
lb3 = Label(w1, text="Choose features for comparison", bg="yellow"
, font=('Arial Black', 18), width=25)
lb4 = Label(w1, text=" ", anchor=CENTER)
fr1 = LabelFrame(w1, width=20, padx=100)
hpw_cb = Checkbutton(fr1, text="Horsepower", variable=hpw, anchor='w', onvalue="Horsepower", offvalue="")
hpw_cb.grid()
hpw_cb.deselect()
mil_cb = Checkbutton(fr1, text="Mileage", variable=mil, anchor='w', onvalue="Mileage", offvalue="")
mil_cb.grid()
mil_cb.deselect()
var_stor = [hpw, mil]
print(hpw)
print(mil)
var_fill = []
for itr1 in var_stor:
if itr1 != "":
var_fill.append(itr1)
print(var_fill)
def car_1():
name1 = StringVar()
c1 = Toplevel()
c1.title("Car 1")
c1.geometry("430x200")
car1_lb1 = Label(c1, text="Car Name:")
name1_ifl = Entry(c1)
name1 = name1_ifl.get()
elm_var_fill = len(var_fill)
ct1 = 0
car1_val = []
for itr2 in var_fill:
if ct1 == elm_var_fill:
break
lb5 = Label(c1, text=itr2.get())
#Creating text field
ftr1_ifl = Entry(c1)
car1_ftr = ftr1_ifl.get()
car1_val.append(car1_ftr)
car1_ftr = None
lb5.grid(row=ct1 + 2, column=1)
ftr1_ifl.grid(row=ct1 + 2, column=2)
ct1 += 1
print(car1_val)
def display():
dp = Toplevel()
dp.title("Results")
dp.geometry("500x200")
car1_pt = 0
car2_pt = 0
car_tree = tktrv.Treeview(dp)
car_tree["columns"] = ("car1col")
car_tree.column("#0", width=120, minwidth=30)
car_tree.column("car1col", width=120, minwidth=30)
car_tree.heading("#0", text="Features" )
car_tree.heading("car1col", text=str(name1))
car_tree.pack()
c1.withdraw()
print(var_fill)
done1_bt = Button(c1, text="Continue", command=display)
name1_ifl.grid(row=0, column=2)
car1_lb1.grid(row=0, column=1)
done1_bt.grid(row=5,column=1)
w1.withdraw()
done_bt = Button(w1, text="Done", command=car_1)
done_bt.grid(row=3, column=1)
lb3.grid(row=0, column=1)
lb4.grid(row=1, column=1)
fr1.grid(row=2, column=1)
root.withdraw()
bt1 = Button(root, text="CARS", width=5, font=('Calibri', 15), command=bt_cars)
bt1.grid(row=7)
space2 = Label(root, text="\n\n")
space2.grid(row=6)
root.mainloop()
I am facing trouble with the variables named: hpw, mil, name1.
Any help would be welcome.
NOTE:- Please excuse the amount of code; I wanted others to replicate the error and see it for themselves
For the variables hpw and mil, these variables are empty strings that's why you are not getting any value from those checkboxes. To get values from the checkboxes replace these lines of code:
var_stor = [hpw, mil]
with
var_stor = [hpw_cb.cget('onvalue'), mil_cb.cget('onvalue')]
since you want the onvalue then you must use cget() method to access those values.
also, replace
lb5 = Label(c1, text=itr2.get())
with
lb5 = Label(c1, text=itr2)
because now you have required values (not objects) in a list, so just need to access those values.
For the variable name1 you can use #BokiX's method.
The problem is you are using get() wrong. You cannot use get() right after Entry() because as soon as entry is created it's getting the input before the user can even input something.
Use this code:
def get_input(text):
print(text)
e = Entry(root)
e.pack()
b = Button(root, text="Print input", command=lambda: get_input(e.get()))
b.pack()
Now get() method will not be executed before you click the button.

Label Not Continually Updating Tkinter

I have read through several answers to similar topics but none of them are relevant to my situation, I am trying to display a list on a label and whenever the button is pressed to update the list the label should update as well but it only updates when submitbtn_name is clicked. Any help appreciated I am very new to Tkinter.
My Code:
from tkinter import *
root = Tk()
root.title("Path Creator")
root.geometry('1680x1080')
root['background'] = '#aaaaaa'
list_of_paths_list = []
path_list = []
name = Entry(root, width=400)
name.insert(0, "Name")
name.pack()
def add_name():
path_list.append(name.get())
list_label = Label(root, text="path name:" + str(path_list))
list_label.pack()
submitbtn_name = Button(root, text="submit name", command=add_name)
submitbtn_name.pack()
value1 = Entry(root, width=400)
value1.insert(0, "value1")
value1.pack()
distance1 = Entry(root, width=400)
distance1.insert(0, "distance1")
distance1.pack()
def submitbtn_value_dist():
temp_list = []
temp_list.append(value1.get())
temp_list.append(distance1.get())
path_list.append(tuple(temp_list))
list_label = Label(root, text="current path: " + path_list)
list_label.pack()
submitbtn_pathpart = Button(root, text="submit path part", )
submitbtn_pathpart.pack()
root.mainloop()
Using f-string format. Added command in submitbtn_pathpart
Snippet:
def submitbtn_value_dist():
temp_list = []
temp_list.append(value1.get())
temp_list.append(distance1.get())
path_list.append(tuple(temp_list))
list_label = Label(root, text=f"current path:{path_list}")
list_label.pack()
submitbtn_pathpart = Button(root, text="submit path part", command=submitbtn_value_dist )
submitbtn_pathpart.pack()
root.mainloop()
Output for name:
Output for value and distance:

How to use class and self here to get two different entries?

With my current code, it does not matter whether I click on "Input Folder" - Change or "JukeBox" change the result always gets displayed in "JukeBox" entry. This is incorrect, using class and self how can I change the code to display result from "Input Folder" - Change in "Input Folder" entry and the result from "Jukbox" - Change in "Jukebox" entry?
Also, how can I save the selected folders to a file so that it is there on app exit and re open?
My code:
import os
from tkinter import *
from tkinter import filedialog
inPut_dir = ''
jukeBox_dir = ''
def inPut():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='Input Folder')
inPut_dir = StringVar()
inPut_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, inPut_dir)
def jukeBox():
opendir = filedialog.askdirectory(parent=root,initialdir="/",title='JukeBox')
jukeBox_dir = StringVar()
jukeBox_dir = os.path.abspath(opendir)
entry.delete(0, END)
entry.insert(0, jukeBox_dir)
root = Tk()
root.geometry("640x240")
root.title("Settings")
frametop = Frame(root)
framebottom = Frame(root)
frameright = Frame(framebottom)
text = Label(frametop, text="Input Folder").grid(row=5, column=2)
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
text = Label(frametop, text="JukeBox").grid(row=6, column=2)
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
ButtonA = Button(frametop, text="Change", command=inPut).grid(row=5, column=28)
ButtonB = Button(frametop, text="Change", command=jukeBox).grid(row=6, column=28)
ButtonC = Button(frameright, text="OK").grid(row=5, column=20, padx=10)
ButtonD = Button(frameright, text="Cancel").grid(row=5, column=15)
frametop.pack(side=TOP, fill=BOTH, expand=1)
framebottom.pack(side=BOTTOM, fill=BOTH, expand=1)
frameright.pack(side=RIGHT)
root.mainloop()
See attached image:enter image description here
Your code has both:
entry = Entry(frametop, width=50, textvariable=inPut_dir)
entry.grid(row=5,column=4,padx=2,pady=2,sticky='we',columnspan=20)
and
entry = Entry(frametop, width=50, textvariable=jukeBox_dir)
entry.grid(row=6,column=4,padx=2,pady=2,sticky='we',columnspan=20)
with jukeBox_dir/row 6 overriding inPut_dir/row 5
Therefore, in def input:
where you have:
entry.insert(0, inPut_dir)
You'll get the result in row 5 (jukebox_dir)

Make Label() display Entry() input but surrounded in quote marks

As I type into Entry "e1", Label "l1" updates to display the entry. I plan to use this later to preview multiple entries in a single line.
My question: How can I get the Label "l1" to display with single quotes around it as I type into Entry "e1". The quotes should only appear when there is text in Entry "e1". They should also be removed if the content in Entry is deleted.
I'm quite new to this so simple answers please.
from tkinter import *
root = Tk()
def printEntry():
complete = var1.get() + var2.get()
print (complete)
var1 = StringVar()
var2 = StringVar()
e1 = Entry(root, width = 15, textvariable = var1)
e1.pack()
l1 = Label(root, textvariable = var1)
l1.pack()
e2 = Entry(root, width = 15, textvariable = var2)
e2.pack()
l2 = Label(root, textvariable = var2)
l2.pack()
b = Button(root, text = "CONFIRM", command = printEntry)
b.pack()
mainloop()
Using the trace method of the StringVar can be used to trigger a function each time the entry is edited:
from tkinter import *
root = Tk()
def printEntry():
complete=var1.get() + var2.get()
print(complete)
def update_l1(*args):
txt = var1.get()
if txt:
l1.configure(text="'%s'" % txt)
else:
l1.configure(text='')
def update_l2(*args):
txt = var2.get()
if txt:
l2.configure(text="'%s'" % txt)
else:
l2.configure(text='')
var1 = StringVar()
var1.trace("w", update_l1)
var2 = StringVar()
var2.trace("w", update_l2)
e1 = Entry(root, width=15, textvariable=var1)
e1.pack()
l1 = Label(root)
l1.pack()
e2 = Entry(root, width=15, textvariable=var2)
e2.pack()
l2 = Label(root)
l2.pack()
b = Button(root, text="CONFIRM", command=printEntry)
b.pack()
mainloop()
UPDATE: Answer to the comment about putting the quotes inside the entry too:
from tkinter import *
root = Tk()
def printEntry():
complete=var1.get()
print(complete)
def update1(*args):
txt = var1.get().strip("'") # remove surronding quotes if present
if txt:
var1.set(r"'%s'" % txt) # add the quotes
else:
var1.set("")
l1.configure(text=var1.get()) # update the label contents
var1 = StringVar()
var1.trace("w", update1)
e1 = Entry(root, width=15, textvariable=var1)
e1.pack()
l1 = Label(root)
l1.pack()
b = Button(root, text="CONFIRM", command=printEntry)
b.pack()
root.mainloop()
For some reason I don't understand, the label did not display the same text as the entry if I used l1 = Label(root, textvariable=var1) (the quotes did not appear immediately), so instead I update the text of l1 inside the function update1.

Tkinter - How to display image when clicking a button?

First time here so forgive me as this is my FIRST attempt at making a silly GUI game (if you want to call it that). I'm trying to get the user to click a button and the image of their selection pops up. I can't seem to figure out how to get the image to pop up though.
Image does show if I run it separately.
My code:
from Tkinter import *
root = Tk()
class PokemonClass(object):
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.WelcomeLabel = Label(root, text="Welcome! Pick your Pokemon!",
bg="Black", fg="White")
self.WelcomeLabel.pack(fill=X)
self.CharButton = Button(root, text="Charmander", bg="RED", fg="White",
command=self.CharClick)
self.CharButton.pack(side=LEFT, fill=X)
self.SquirtButton = Button(root, text="Squirtle", bg="Blue", fg="White")
self.SquirtButton.pack(side=LEFT, fill=X)
self.BulbButton = Button(root, text="Bulbasaur", bg="Dark Green",
fg="White")
self.BulbButton.pack(side=LEFT, fill=X)
def CharClick(self):
print "You like Charmander!"
global CharSwitch
CharSwitch = 'Yes'
CharSwitch = 'No'
if CharSwitch == 'Yes':
CharPhoto = PhotoImage(file="Charmander.gif")
ChLabel = Label(root, image=CharPhoto)
ChLabel.pack()
k = PokemonClass(root)
root.mainloop()
This works, but the actual image no longer shows, if I keep the PhotoImage OUT of the class it will print but I want to have it print IF they click the specific button:
from Tkinter import *
root = Tk()
class PokemonClass(object):
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.WelcomeLabel = Label(root, text = "Welcome! Pick your Pokemon!", bg = "Black", fg = "White")
self.WelcomeLabel.pack(fill = X)
self.CharButton = Button(root, text = "Charmander", bg = "RED", fg = "White", command = CharClick)
self.CharButton.pack(side = LEFT, fill = X)
self.SquirtButton = Button(root, text = "Squirtle", bg = "Blue", fg = "White")
self.SquirtButton.pack(side = LEFT, fill = X)
self.BulbButton = Button(root, text = "Bulbasaur", bg = "Dark Green", fg = "White")
self.BulbButton.pack(side = LEFT, fill = X)
def CharClick():
print "You like Charmander!"
CharPhoto = PhotoImage(file = "Charmander.gif")
ChLabel = Label(root, image = CharPhoto)
ChLabel.pack()
k = PokemonClass(root)
root.mainloop()
You need to maintain a reference to your PhotoImage object. Unfortunately there is an inconsistency in tkinter in that attaching a Button to a parent widget increments the reference count, but adding an image to a widget does not increment the reference count. As a consequence at the moment the CharPhoto variable goes out of scope at the end of the function CharClick, the number of reference to the PhotoImage falls to zero and the object is made available for garbage collection.
If you keep a reference to the image somewhere, it will appear. When you kept it globally it remained in scope for the entire script and hence appeared.
You can keep a reference to it in the PokemonClass object or in the Label widget.
Below is the later of those options
from Tkinter import *
root = Tk()
class PokemonClass(object):
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.WelcomeLabel = Label(root, text="Welcome! Pick your Pokemon!",
bg="Black", fg="White")
self.WelcomeLabel.pack(fill=X)
self.CharButton = Button(root, text="Charmander", bg="RED", fg="White",
command=self.CharClick)
self.CharButton.pack(side=LEFT, fill=X)
self.SquirtButton = Button(root, text="Squirtle", bg="Blue", fg="White")
self.SquirtButton.pack(side=LEFT, fill=X)
self.BulbButton = Button(root, text="Bulbasaur", bg="Dark Green",
fg="White")
self.BulbButton.pack(side=LEFT, fill=X)
def CharClick(self):
print "You like Charmander!"
global CharSwitch
CharSwitch = 'Yes'
CharPhoto = PhotoImage(file="Charmander.gif")
ChLabel = Label(root, image=CharPhoto)
ChLabel.img = CharPhoto
ChLabel.pack()
CharSwitch = 'No'
k = PokemonClass(root)
root.mainloop()
The solution which helped me is just simply declaring all the image variables on the next line after 'root = Tk()'. Doing so won't spoil your code or anything.

Categories

Resources