Tkinter create clear button to clear various textbox - python

I have around 40 textboxes named from d1 to d40.
Currently I have created a Clear Button with 40 lines, each line stating the textbox number (eg: "d1.delete(0, END)" to clear the textbox).
I know there should be a smarter way... but I tried many times and failed.
Below please find extract of my code:
import tkinter as tk
from tkinter import *
win = Tk()
win.wm_title("Testing")
win.wm_geometry("400x400+10+30")
v = StringVar()
v.set('abcd')
d1 = Entry(win, text=v)
d1.place(x=10, y=10, height=30, width=400)
s = StringVar()
s.set('abc22222222')
d2 = Entry(win, text=s)
d2.place(x=10, y=50, height=30, width=400)
t = StringVar()
t.set('abc22sdfefe222222')
d3 = Entry(win, text=t)
d3.place(x=10, y=90, height=30, width=400)
def clearcomm():
n = 0
for i in range(3):
n +=1
'd{}.delete(0, END)'.format(n)
Button(win, text='Clear', command=clearcomm, height=1, width=6, font=("arial", 7, "bold"), fg="white", bg="red").place(x=10, y=150)
mainloop()
then I also tried:
clearlist = []
n = 0
for i in range(3):
n +=1
command = 'd{}.delete(0, END)'.format(n)
clearlist.append(command)
n = 0
def clearcomm():
for list in clearlist:
return
but this one no response...so I do not know how to do it. Very grateful if you can give some advise.

The smarter way you probably look for is a list of all textboxes you want to clear:
global textboxes
textboxes = []
global contents
contents = []
for y in [10,50,90]:
v = StringVar()
v.set('sometext')
d1 = Entry(win, textvariable=v)
d1.place(x=10, y=y, height=30, width=400)
textboxes.append(d1)
contents.append(v)
You then have two lists. One containing all entry widgets, the other containing all contents. You can manipulate both using for-loops to iterate over all objects:
def clearcomm():
for c in contents:
c.set('')
or
def clearcomm():
for t in textboxes:
t.delete(0,END)
Both should work since you use textvariables.
[EDIT: global statements moved uniformly to the front. Thanks for noting, Cool Cloud.]

Related

How to enable a disabled Button after filling Entry widgets?

I have 2 Entrys and one button. I want to make that button's state disabled until the two Entrys are filled in. How can I achieve that?
howManyStocksLabel = Label(root, text = "How many stocks do you want to evaluate?")
howManyStocksLabel.grid(row = 1, column = 0)
howManyStocksEntry = Entry(root, borderwidth = 3)
howManyStocksEntry.grid(row = 1, column = 1)
riskLabel = Label(root, text = "Enter risk %")
riskLabel.grid(row = 2, column = 0, sticky = 'w')
riskEntry = Entry(root, borderwidth = 3)
riskEntry.grid(row = 2, column = 1)
nextButton = Button(root, text = "Next!", width = 20, height = 2,state = DISABLED,
fg = 'green', bg = 'white',
command= lambda: myClick(riskEntry, howManyStocksEntry, var))
nextButton.grid(row = 4, column = 1)
I tried to check whether the entries are filled in or not by:
if(riskEntry.get() != ""):
....................
but it just doesn't work.
You need to check if the value is there after the user inputs it. Also, you can use tk.StringVar() as a text variable and trace it.
Here is an example:
import tkinter as tk
def check_entry(*args):
if r1.get() and r2.get():
b1.config(state='normal')
else:
b1.config(state='disabled')
root = tk.Tk()
r1 = tk.StringVar(master=root)
r2 = tk.StringVar(master=root)
e1 = tk.Entry(root, textvariable=r1)
e1.pack()
e2 = tk.Entry(root, textvariable=r2)
e2.pack()
b1 = tk.Button(root, text='Click Me!', state='disabled')
b1.pack()
r1.trace('w', check_entry)
r2.trace('w', check_entry)
root.mainloop()
You will need to use a binding on your entry widgets to check whether the user has entered anything into the entry or not.
This code will fire the check_entry function every time the user types in one of the entry boxes:
riskEntry.bind('<KeyRelease>', check_entry)
howManyStocksEntry.bind('<KeyRelease>', check_entry)
Then your check_entry function might look like this:
def check_entry(event): #event is required for all functions that use a binding
if riskEntry.get() and howManyStocksEntry.get():
nextButton.config(state=NORMAL)
else:
nextButton.config(state=DISABLED)
One way to do it would be to utilize the ability to "validate" their contents that Entry widgets support — see adding validation to an Entry widget — but make it check the contents of multiple Entry widgets and change the state of a Button accordingly.
Below shows how to do this via a helper class that encapsulates most of the messy details needed to make doing it relatively painless. Any number of Entry widgets can be "watched", so it scales well to handle forms consisting of many more than merely two entries.
from functools import partial
import tkinter as tk
from tkinter.constants import *
class ButtonEnabler:
""" Enable/disable a Button depending on whether all specified Entry widgets
are non-empty (i.e. contain at least one character).
"""
def __init__(self, button, *entries):
self.button = button
self.entries = entries
for entry in self.entries:
func = root.register(partial(self.check_entries, entry))
entry.config(validate="key", validatecommand=(func, '%P'))
def check_entries(self, this_entry, new_value):
other_entries = (entry for entry in self.entries if entry is not this_entry)
all_others_filled = all(entry.get() for entry in other_entries)
combined = bool(new_value) and all_others_filled
self.button.config(state=NORMAL if combined else DISABLED)
return True
root = tk.Tk()
howManyStocksLabel = tk.Label(root, text="How many stocks do you want to evaluate?")
howManyStocksLabel.grid(row=1, column=0)
howManyStocksEntry = tk.Entry(root, borderwidth=3)
howManyStocksEntry.grid(row=1, column=1)
riskLabel = tk.Label(root, text="Enter risk %")
riskLabel.grid(row=2, column=0, sticky='w')
riskEntry = tk.Entry(root, borderwidth=3)
riskEntry.grid(row=2, column=1)
nextButton = tk.Button(root, text="Next!", width=20, height=2, state=DISABLED,
fg='green', bg='white', disabledforeground='light grey',
command=lambda: myClick(riskEntry, howManyStocksEntry, var))
nextButton.grid(row=4, column=1)
enabler = ButtonEnabler(nextButton, howManyStocksEntry, riskEntry)
root.mainloop()

how to get the the value from the entry widget in tkinter in python3.6

I'm trying to get the data from the entry box.I'm not getting the use of those variables. It's showing me blank when I try to print the result. I tried using lambda but still not working. I'm new at this. Please show me where I'm wrong. I tried online but they are older version solutions.
def insertdata(E1):
print(E1)
e1 = StringVar()
L1 = Label(F1, text ="Serial No:",anchor = E)
L1.grid(row = 0 ,column = 0)
E1 = Entry(F1,textvariable = e1)
E1.grid(row = 0 ,column = 2, sticky = N)
v1 = e1.get()
Button (F2,text = "Paid",command=lambda:insertdata(v1)).pack(side= TOP)
This how to get content in entry widget and print. With the code you posted, you are doing a lot of wrong things; you cannot use pack and grid to postion your widget in the same window. Also never do this: Button (F2,text = "Paid",command=lambda:insertdata(v1)).pack(side= TOP), but always position your layout manager on the next line.
EXAMPLE
b = Button (F2,text = "Paid",command=lambda:insertdata(v1))
b.pack(side= TOP)
FULL CODE
from tkinter import *
def insertdata():
print(e1)
print(E1.get())
root = Tk()
L1 = Label( text="Serial No:", anchor=E)
L1.grid(row=0, column=0)
e1 = StringVar()
E1 = Entry( textvariable=e1)
E1.grid(row=0, column=2, sticky=N)
b = Button( text="Paid", command=insertdata)
b.grid(row=10, column=30)
root.mainloop()
You have set v1 to e1.get() before anything could be entered into the entry.
I tried the following code, and it works fine.
from tkinter import * # SHOULD NOT USE.
F1=Tk()
F2=Tk()
def insertdata(E1):
print(E1)
e1 = StringVar()
L1 = Label(F1, text ="Serial No:",anchor = E)
L1.grid(row = 0 ,column = 0)
E1 = Entry(F1,textvariable = e1)
E1.grid(row = 0 ,column = 2, sticky = N)
Button (F2,text = "Paid",command=lambda:insertdata(e1.get())).pack(side= TOP) # SHOULD NOT USE.

Making a Tkinter Listbox with Scrolll

I'm currently trying to make a Listbox with a Scroll bar on the side appear on my Tkinter Window. I can't figure out how to make the Scrollbar size the same size as my listbox. Heres my code:
global R3
global lb
R3 = Tk()
gg = "white"
g = "blue"
R3.geometry('720x720')
R3.title(username + " Dropbox")
R3.resizable(width=False, height=False)
logoutbt = Button(R3, text="Logout", width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE, command=rectologout)
upload = Button(R3, text="Upload", width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE, command=rectoupload)
logoutbt.place(x=220, y=500)
upload.place(x=480, y=500)
button1 = Button(R3, text='Receive file', width=10, height=2, bg=g, fg=gg, font="5", relief=RAISED, overrelief=RIDGE,command = get_file)
lb = Listbox(R3, height=6,width = 15)
s.send("RETREIVEA-"+username)
file_list = s.recv(1024).split("-")
if file_list == [""]:
button1.config(state = DISABLED)
for file in file_list:
lb.insert("end", file)
yscroll = Scrollbar(R3, orient=VERTICAL)
lb['yscrollcommand'] = yscroll.set
yscroll['command'] = lb.yview
lb.place(x=280,y=200)
yscroll.place(x=370,y=200)
button1.place(x=400, y=200)
R3.mainloop()
Any suggestions on how to do it?
First of all, please read how to create a Minimal, Complete and Verifiable example.
Your code lacks imports and references non-initialized objects / variables / functions.
How to achieve what you want?
Either use grid instead of place or pass height parameters to lb.place(..., height=<whatever you want>) and yscroll.place(..., height=<whatever you want>)

How can I dynamically create ttk widgets depending on the value entered in a ttk.entry box?

I am trying to make a GUI where as soon as the user inputs an integer into a ttk.entry field, that many checkbuttons need to appear below it. For example, if they put "5" into the entry widget, 5 check buttons need to appear below the entry field.
Edit:
What I ended up using:
self.number_of_stages = tk.IntVar()
self.check_box_dict={}
self.num_of_stages={}
self.stagetempvar={}
self.equipment_widgets={}
def centrifugal_compressor_widgets(self):
self.equipment_widgets.clear()
self.equipment_widgets["NumOfStagesLabelCentComp"]=tk.Label(self.parent, text="Number of Stages:", bg="white")
self.equipment_widgets["NumOfStagesLabelCentComp"].place(relx=0.5, y=260, anchor="center")
self.equipment_widgets["NumOfStagesEntryCentComp"]=ttk.Entry(self.parent, textvariable=self.number_of_stages)
self.equipment_widgets["NumOfStagesEntryCentComp"].place(relx=0.5, y=290, anchor="center")
def OnTraceCentComp(self, varname, elementname, mode):
for key in self.check_box_dict:
self.check_box_dict[key].destroy()
try:
if self.number_of_stages.get() <=15 :
i=1
self.stagetempvar.clear()
while i <= self.number_of_stages.get():
self.stagetempvar[i]=tk.StringVar()
self.stagetempvar[i].set("Closed")
self.check_box_dict[i]=ttk.Checkbutton(self.parent, text=i, offvalue="Closed", onvalue="Open",variable=self.stagetempvar[i])
self.check_box_dict[i].place(relx=(i*(1/(self.number_of_stages.get()+1))), y=360, anchor="center")
i+=1
except:
pass
take a look at the below and let me know what you think...
A very ugly, super basic example:
from Tkinter import *
root = Tk()
root.geometry('200x200')
root.grid_rowconfigure(0, weight = 1)
root.grid_columnconfigure(0, weight = 1)
win1 = Frame(root, bg= 'blue')
win1.grid(row=0, column=0, sticky='news')
number = IntVar()
entry = Entry(win1, textvariable = number)
entry.pack()
confirm = Button(win1, text = 'Press to create widgets...', command = lambda:create_widgets(number.get()))
confirm.pack()
def create_widgets(number):
for n in range(0,number):
Checkbutton(win1, text = 'Checkbutton number : %s' % n).pack()
root.mainloop()

Make a dictionary using tkinter, GUI

I want to make a dictionary by using a GUI, I was thinking of making two entries, one for the object and the other for the key. And I want to make a button that execute the information and add it to the empty dictionary.
from tkinter import *
fL = {}
def commando(fL):
fL.update({x:int(y)})
root = Tk()
root.title("Spam Words")
label_1 = Label(root, text="Say a word: ", bg="#333333", fg="white")
label_2 = Label(root, text="Give it a value, 1-10:", bg="#333333", fg="white")
entry_1 = Entry(root, textvariable=x)
entry_2 = Entry(root, textvariable=y)
label_1.grid(row=1)
label_2.grid(row=3)
entry_1.grid(row=2, column=0)
entry_2.grid(row=4, column=0)
but = Button(root, text="Execute", bg="#333333", fg="white", command=commando)
but.grid(row=5, column=0)
root.mainloop()
I want to use that dictionary later in my main program. You see if it would be a function, I would just go in IDLE and do..
def forbiddenOrd():
fL = {}
uppdate = True
while uppdate:
x = input('Object')
y = input('Key')
if x == 'Klar':
break
else:
fL.update({x:int(y)})
return fL
And then just use the function further on in my program
Any suggestions?
I appreciate it. Thank you
You are close to achieving what you want. There are a few modifications that need to be made. First, lets start with the entry boxes entry_1 and entry_2. Using a text variable like you did is a good approach; however I did not see them defined, so here they are:
x = StringVar()
y = StringVar()
Next, we need to change how you call the commando function and what parameters you pass though it. I want to pass the x and y values though, but I can't do this by just using something like command=commando(x.get(), y.get()), I need to use lambda as follows:
but = Button(root, text="Execute", bg="#333333", fg="white", command=lambda :commando(x.get(), y.get()))
Now why did I pass the values x and y as x.get() and y.get()? In order to get the values from a tkinter variable such as x and y, we need to use .get().
Finally, let's fix the commando function. You cannot use it as you did with fL being the parameter. This is because any parameter you set there becomes a private variable to that function even if it appears elsewhere in you code. In other words, defining a function as def commando(fL): will prevent the fL dictionary outside the function from being assessed within commando. How do you fix this? Use different parameters. Since we are passing x and y into the function, let's use those as parameter names. This is how our function looks now:
def commando(x, y):
fL.update({x:int(y)})
This will create new items in your dictionary. Here is the completed code:
from tkinter import *
fL = {}
def commando(x, y):
fL.update({x:int(y)}) # Please note that these x and y vars are private to this function. They are not the x and y vars as defined below.
print(fL)
root = Tk()
root.title("Spam Words")
x = StringVar() # Creating the variables that will get the user's input.
y = StringVar()
label_1 = Label(root, text="Say a word: ", bg="#333333", fg="white")
label_2 = Label(root, text="Give it a value, 1-10:", bg="#333333", fg="white")
entry_1 = Entry(root, textvariable=x)
entry_2 = Entry(root, textvariable=y)
label_1.grid(row=1)
label_2.grid(row=3)
entry_1.grid(row=2, column=0)
entry_2.grid(row=4, column=0)
but = Button(root, text="Execute", bg="#333333", fg="white", command=lambda :commando(x.get(), y.get())) # Note the use of lambda and the x and y variables.
but.grid(row=5, column=0)
root.mainloop()

Categories