Tkinter Button Callback Lambda Unexpected Result - python

I want to create multiple rows of tkinter widgets and I thought storing them in a dictionary would be a clean way to do this. I'm having trouble getting the callbacks for the buttons to work correctly though. With the code as is, the value passed to the button callback is always E and I can't see why that is. How do I pass the correct key to the callback please - i.e. A for the first row, B for the second etc?
import tkinter as tk
NUM_ROWS = 5
BOLD_FONT = ("calbri", 16, "bold")
NORMAL_FONT = ("calbri", 16, "normal")
def submit():
print("you win")
def clear(key):
print(key)
# widgets[key]["factor_field"].delete(0,"end")
# widgets[key]["factor_field"].insert(0, key)
data = {}
widgets = {}
root = tk.Tk()
# Build widgets
for i in range(NUM_ROWS):
key = chr(i + 65)
this_row = widgets[key] = {}
this_row["label"] = tk.Label(root, text=key, font=BOLD_FONT)
this_row["label"].grid(row=i, column=0, padx=5, pady=10)
this_row["factor_field"] = tk.Entry(root, width=60, font=NORMAL_FONT)
this_row["factor_field"] .grid(row=i, column=1, padx=5, pady=10)
this_row["target_node_field"] = tk.Entry(root, width=5, font=NORMAL_FONT)
this_row["target_node_field"].grid(row=i, column=2, padx=5, pady=10)
this_row["clear_button"] = tk.Button(root, text="Clear", command=lambda: clear(
key), font=BOLD_FONT).grid(row=i, column=3, padx=5, pady=10)
submit_button = tk.Button(root, text="Submit", command=submit,
font=BOLD_FONT).grid(row=NUM_ROWS + 1, column=0, padx=5, pady=10)
print(widgets)
root.mainloop()

Use this:
this_row["clear_button"] = tk.Button(root, text="Clear",
command=lambda x=key: clear(x),
font=BOLD_FONT)
this_row["clear_button"].grid(row=i, column=3, padx=5, pady=10)
In your current code, the value for the key variable is fixed at E after the for loop has completed. As a result, your existing lambda function will always call clear('E').

Related

change label text in widgets created in loop dynamically from a dictionary

Im working on a tkinter GUI that creates labels from a dictionary.
on of the labels is a "Fails" counter (theres another function that updates this value in the dictionary) id like if so when the "fails" is updated in the dictionary, it updates the fails value in the label.
heres a snippet if createing the labels from the dictionary. i cant figure out how to make it so the fails_label text is changed when the dictionary is updated
Thank you
row = 2
widgets = {}
for key in obj2create:
strEngNumber = obj2create[key][0]
strLayer = obj2create[key][1]
strFile = obj2create[key][2]
intFails = obj2create[key][3]
strJobKey = key
job_label = tk.Label(self.frame, text=key, anchor="w",
justify="center", wraplength=701,background=bg)
job_label.grid(row=row, column=0, pady=10, padx=10, ipady=3)
eng_label = tk.Label(self.frame, text=strEngNumber, anchor="w",
justify="center", wraplength=701,background=bg)
eng_label.grid(row=row, column=1, pady=10, padx=10, sticky="w")
layer_label = tk.Label(self.frame, text=strLayer, anchor="w",
justify="center", wraplength=701,background=bg)
layer_label.grid(row=row, column=2, pady=10, padx=10, sticky="w")
file_label = tk.Label(self.frame, text=strFile, anchor="w",
justify="center", wraplength=701,background=bg)
file_label.grid(row=row, column=3, pady=10, padx=10, sticky="w")
fails_label = tk.Label(self.frame, text=intFails, anchor="w",
justify="center", wraplength=701,background=bg)
fails_label.grid(row=row, column=4, pady=10, padx=10, sticky="w")
You can use trace_add() method like in the example below:
from tkinter import *
def update(var, index, mode):
label.configure(text=intFails.get())
def functionOnClick():
intFails.set(intFails.get() + 1)
w = Tk()
w.geometry('400x400')
intFails = IntVar(w, 0)
intFails.trace_add('write', update)
label = Label(w, textvariable=intFails, anchor="w", justify="center", font=('Arial', 22))
label.place(x=0, y=0)
btn = Button(w, text='Click', command=functionOnClick, font=('Arial', 22))
btn.place(x=0, y=80, width = 100, height = 80)
w.mainloop()
This method helps you to automatically detect, when variable was changed. Though it works only with special IntVar() and StringVar(), but I think it's only possible way to do this at least with this type of vars.
On the other hand, you can try to create a class with dictionary as your field and works with it by set property. This link may be useful for you.

Pass widget name on button click

Can someone help, i need to generate 10 buttons and then when i click it must change the text on the unnamed button.
trying to get the event.widget but with no successes
from tkinter import ttk
root = ttk()
def gonow(e):
e.config(text="clicked")
for x in range(0, 10):
ttk.Button(root, name="but"+x,width="30", height=3, text=x).grid( column=0,
r.ow=0, padx=10, pady=5)
butok=ttk.Button(root, width="30", height=3, text=x, command=lambda var="but"+x:
gonow(var)).grid( column=0, row=0, padx=10, pady=5)
if __name__ == "__main__":
root.mainloop()
New update
b = tk.Button(frm_txt_json_case_btn, width="30", height=3, text=str(titulo+" "+cherep), fg=fcolor,relief=relifst, borderwidth=4,command=lambda titulo=titulo,wrd2srch=words2search,assumirrow=assumirrow,hiden_row=assumirrowr,resp_kib=resp_kiblog,repkib=repkib,urrrl=url_conf, jsump=jsonreq, explis=expectresq, frm_txt_json_case_tit=frm_txt_json_case_tit, inp_cond_protocol=inp_cond_protocol, resp_json=resp_json_input,lblexp=lblexpect, reqtxt=reqst_input,frm_txt_json_case_btn=frm_txt_json_case_btn: ChangConfWI(reqtxt, lblexp, frm_txt_json_case_tit, resp_json, inp_cond_protocol,urrrl, jsump, explis,frm_txt_json_case_btn,repkib,resp_kib,wrd2srch,hiden_row,assumirrow,titulo))
b.grid(column=colcount, row=rowcount, padx=10, pady=5)
buttonslst.append(b)
valbut=int(assumirrowr)-8
print(valbut)
print(buttonslst[valbut])
fvarbut=buttonslst[valbut]
print(fvarbut)
ttk.Button(frm_but_oknot, width="15", text="OK", image=photoOK, command=lambda assumirrow=assumirrow,filename=filename_report,exp=lblexpect,obs=resp_kiblog,urrrl=url_conf,tipo_de_conf=tipo_de_conf, resp_json_input=resp_json_input, reqst_input=reqst_input: savetoxls("geradorteste",resp_json_input,reqst_input, "OK",tipo_de_conf,urrrl,obs,exp,filename,assumirrow,fvarbut)).grid( column=0, row=0, padx=1, pady=15)
When you pass x to gonow, it is the index of the button, not the button itself. You could store the buttons in a list (note: the buttons, not the result of grid!), and then use the index:
buttons = []
for x in range(0, 3):
b = tk.Button(root, width=30, height=3, text=x, command=lambda x=x: gonow(buttons[x]))
b.grid(column=0, row=x, padx=10, pady=5)
buttons.append(b)
Or postpone the command creation after the button is created and pass the button itself:
for x in range(0, 3):
b = tk.Button(root, width=30, height=3, text=x)
b.config(command=lambda b=b: gonow(b))
b.grid(column=0, row=x, padx=10, pady=5)
(Note: There are a few more unrelated (syntax) errors throughout your code that you should fix.)

Searchable treeview tkinter

I want to code a searchable ttk.Treeview; however, my code does not behave properly. When I type in and click search nothing happens. What should be improved so the searched items are highlighted when I type in?
from tkinter import *
from tkinter import ttk
root = Tk()
root.title("Medicine database")
def add():
tree.insert("",END,values=("",e1.get()))
def search(item=''):
children = tree.get_children(item)
for child in children:
text = tree.item(child, 'text')
if text.startswith(e1.get()):
tree.selection_set(child)
return True
else:
res = search(child)
if res:
return True
lb1 = Label(root,text="Search:")
lb1.grid(row =0,column=0,padx=10,pady=10,sticky=W)
e1=Entry(root,width=15)
e1.grid(row=0,column=1,padx=10,pady=10,sticky=E,rowspan=1)
btn = Button(root,text="search",width=10,command=search)
btn.grid(row =0,column=0,padx=10,pady=10,rowspan=2)
btn1 = Button(root,text="add",width=10,command=add)
btn1.grid(row =1,column=0,padx=10,pady=10,rowspan=2)
#treeview
tree = ttk.Treeview(root,height=25)
tree["columns"]=("one","two","three","four")
tree.column("one",width=120)
tree.column("two",width=160)
tree.column("three",width=130)
tree.column("four",width=160)
tree.heading("one", text="Numer seryjny leku")
tree.heading("two", text="Nazwa Leku")
tree.heading("three", text="Ampułki/Tabletki")
tree.heading("four",text="Data ważności")
tree["show"]="headings"
tree.grid(row=0,column=2,rowspan=6,pady=20)
root.geometry("840x580")
root.mainloop()
As it was, your search method did nothing.
First, you probably need to have an entry for adding items and another for searching them.
Then, in the search method, you must retrieve the query from the search entry, match it with then tree children values, and return (here we will print) the values if you find a match, and highlight them in the Treeview.
import tkinter as tk
from tkinter import ttk
def add():
value = add_entry.get()
values.append(value)
tree.insert("", tk.END, values=(f'#{len(values)}', value, 'more', 'moar'))
def search():
query = search_entry.get()
selections = []
for child in tree.get_children():
if query in tree.item(child)['values']:
print(tree.item(child)['values'])
selections.append(child)
print('search completed')
tree.selection_set(selections)
values = []
root = tk.Tk()
root.title("Medicine database")
lb1 = tk.Label(root, text="Search:")
lb1.grid(row=0, column=0, padx=10, pady=10, sticky=tk.W)
search_entry = tk.Entry(root, width=15)
search_entry.grid(row=0, column=1, padx=10, pady=10, sticky=tk.E, rowspan=1)
btn = tk.Button(root, text="search", width=10, command=search)
btn.grid(row=0, column=0, padx=10, pady=10, rowspan=2)
add_lb = tk.Label(root, text="add:")
add_lb.grid(row=1, column=0, padx=10, pady=10, sticky=tk.W)
add_entry = tk.Entry(root, width=15)
add_entry.grid(row=1, column=1, padx=10, pady=10, sticky=tk.E, rowspan=1)
btn1 = tk.Button(root, text="add", width=10, command=add)
btn1.grid(row=1, column=0, padx=10, pady=10, rowspan=2)
# treeview
tree = ttk.Treeview(root, height=25)
tree["columns"] = ("one", "two", "three", "four")
tree.column("one", width=120)
tree.column("two", width=160)
tree.column("three", width=130)
tree.column("four", width=160)
tree.heading("one", text="Numer seryjny leku")
tree.heading("two", text="Nazwa Leku")
tree.heading("three", text="Ampułki/Tabletki")
tree.heading("four", text="Data ważności")
tree["show"]="headings"
tree.grid(row=0, column=2, rowspan=6, pady=20)
root.geometry("840x580")
if __name__ == '__main__':
root.mainloop()

What can I do to make the frame without widgets?

What I want the frame to do is that when I click on the 'clear' button, the frame is cleaned but it does not and when I enter a string that is not valid and then a valid one, it shows traces of the past and past action. I already tried changing the Label.grid () by a Label.pack (), but it is worse since the 'animation' looks like a stack without removing any element when the 'clear' button is pressed
This is basically what would make it change
from tkinter import *
import tkinter.ttk as ttk
def clear():
area.delete(0,END)
frame.config(bd=1, relief=SUNKEN)
frame.update()
status = Label(frame)
status.grid(row=0, column=0, sticky=NSEW)
def statusVal(value):
if not value == 0:
status = Label(frame, background="#ff4242", fg="#262626", text="Cadena invalida", anchor="center")
status.grid(row=0, column=0)
frame.config(bd=1, relief=SUNKEN, background="#ff4242")
frame.update()
else:
status = Label(frame, background="#56ed42", fg="#262626", text="Cadena valida", anchor="center")
status.grid(row=0, column=0)
frame.config(bd=1, relief=SUNKEN, background="#56ed42")
frame.update()
#Test
def validation():
capture = area.get()
if capture == '1':
return statusVal(0)
else:
return statusVal(1)
root = Tk()
root.geometry("300x150+300+300")
area = Entry(root)
area.grid(row=1, column=0, columnspan=2, sticky=E+W+S+N, padx=5)
frame = Frame(root, bd=1, relief=SUNKEN)
frame.grid(row=2, column=0, padx=5, pady=5, columnspan=2, sticky=W+E+S+N)
frame.columnconfigure(0,weight=5)
frame.rowconfigure(0,weight=5)
abtn = Button(root, text="Validate", command=validation)
abtn.grid(row=1, column=3)
cbtn = Button(root, text="Clear", command=clear)
cbtn.grid(row=2, column=3, pady=5)
root.mainloop()
See if this works better. The main change was to have the status Label always exist and hide or unhide it as desired — instead of creating a new one every time the validation() function was called. I also removed the code that was explicitly updating the frame which isn't necessary.
from tkinter import *
import tkinter.ttk as ttk
def clear():
area.delete(0,END)
status.grid_remove() # Hide. but remember grid options.
def statusVal(value):
if not value == 0:
status.config(background="#ff4242", fg="#262626", text="Cadena invalida",
anchor="center")
status.grid() # Unhide
else:
status.config(background="#56ed42", fg="#262626", text="Cadena valida",
anchor="center")
status.grid() # Unhide
#Test
def validation():
capture = area.get()
if capture == '1':
statusVal(0)
else:
statusVal(1)
# Main
root = Tk()
root.geometry("300x150+300+300")
area = Entry(root)
area.grid(row=1, column=0, columnspan=2, sticky=E+W+S+N, padx=5)
frame = Frame(root, bd=1, relief=SUNKEN)
frame.grid(row=2, column=0, padx=5, pady=5, columnspan=2, sticky=W+E+S+N)
frame.columnconfigure(0,weight=5)
frame.rowconfigure(0,weight=5)
# Initialize status Label.
status = Label(frame, anchor="center")
status.grid(row=0, column=0)
status.grid_remove() # Hide it.
abtn = Button(root, text="Validate", command=validation)
abtn.grid(row=1, column=3)
cbtn = Button(root, text="Clear", command=clear)
cbtn.grid(row=2, column=3, pady=5)
root.mainloop()

Using StringVar data as a list

I've been following this website for a while. It is really helpful. So, thanks for all the useful tips.
I've been searching for this answer for the past two weeks without any success, so now I'm compelled to ask out of total frustration with my current obstacle.
How do you use StringVar as a list?
Basically, I was coding the following program for my wife. The code is pretty messy as it is my first program I've tried to code.
The idea was that I would take 3 variables; password, secret number and website and then do some work on them using if statements and lists to create a unique password.
First problem was that I couldn't restrict the character length of the entry widgets but in the end i solved that but i still want to limit the characters that can be input.
for instance in the website entry box, i want to allow only letters.
If I could convert StringVar to a list, I could do some work with messy if statements to allow only certain characters in each index but everythime i try it says that stringvars cant be used as a list.
I need them as a list to limit the type of characters that can be entered and also so that i can do work on the variables to get the final output.
CODE:
from Tkinter import *
import Tkinter
from PIL import Image, ImageTk
import os
Title= ("Helvetica", 20, "bold", "underline")
Heading= ("Courier", 20, "bold")
Body= ("Courier", 15)
Body1= ("Courier", 15, "bold")
notice= ("Courier", 10)
Body2= ("Courier", 15, "bold", "underline")
root = Tk()
root.title("Koala Series: Encrypter")
root.configure(background="#ffefd5")
root.geometry('{}x{}'.format(510, 600))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1) # not needed, this is the default behavior
root.rowconfigure(1, weight=1)
root.rowconfigure(2, weight=1)
website = StringVar()
Titlemsg = Label(root, text="Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
Titlemsg.grid( row=7, pady=25, sticky=N+S+E+W)
img1 = ImageTk.PhotoImage(Image.open("koala.jpeg"))
startpic = Label(root, image = img1, relief=RIDGE )
startpic.grid( row=10,pady=25, )
Head = Label(root,anchor=CENTER,text="Welcome to the Koala Encrypter \n\n A Koala series tool that allows you\n\n to Encrypt your passwords \n\n Click \'Start Encrypting\' to continue \n\n", font=Body, bg="#ffefd5", relief=RAISED,)
Head.grid( row=14, pady=25, columnspan=2, sticky=N+S+E+W)
web = Label(root, text="WEBSITE: ", font=Body, bg="#ffefd5", justify=CENTER,)
#website.set("Enter your website here")
entry = Entry(root,textvariable=website , justify=CENTER,relief=SUNKEN,cursor="pencil", takefocus=True )
Notice1 = Label( text="Please only insert the first 5 letters of the website!!",font=notice, bg="#ffefd5", fg="#0000ff",)
passw = Label(root, text="PASSWORD: ", font=Body, bg="#ffefd5", justify=CENTER)
passwordvar= StringVar()
entry1 = Entry(root, textvariable= passwordvar, justify=CENTER,relief=SUNKEN, cursor="pencil", takefocus=True )
Notice= Label(root, text="Your password must only be 5 characters long!!", font=notice, bg="#ffefd5", fg="#0000ff", justify=CENTER)
def callback(event):
if "<0>":
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Your secret number must be between 1 and 9:", font=Body1, fg="red", bg="#ffefd5")
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
secret = Label(root, text="SECRET NUMBER: ", font=Body, bg="#ffefd5" , justify=CENTER,)
numbervar = StringVar()
entry2 = Entry(root, textvariable=numbervar , justify=CENTER,relief=SUNKEN,cursor="pencil", takefocus=True)
entry2.bind("<0>", callback)
Notice2 = Label(root, text="your secret number must be between 1 and 9!!!", font=notice, bg="#ffefd5", fg="#0000ff", justify=CENTER)
img = ImageTk.PhotoImage(Image.open("Koalalogo.jpg"))
panel = Label(root, image = img, relief=SUNKEN)
correct= Label(root, text="Check the below details \n\n Click \'yes\' if they are correct \n\n Click \'No\' to go back \n\n", font=Body1, bg="#ffefd5")
yourwebsite = Label(root, text="The Website is :", font=Body, bg="#ffefd5")#
website1 = Label(root, font=Body2, bg="#ffefd5",fg= "#00009C", textvariable = website)#
yourpassword = Label(root, text="Your Password is:", font=Body, bg="#ffefd5")
yournumber1= Label(root, font=Body2, bg="#ffefd5",textvariable = numbervar , fg= "#00009C", )
yourpassword1 = Label(root, font=Body2, bg="#ffefd5",textvariable = passwordvar , fg= "#00009C", )
yournumber= Label(root, text="Your Secret Number is:", font=Body, bg="#ffefd5")
def restart():
Titlemsg.grid_forget()
correct.grid_forget()
yourwebsite.grid_forget()
website1.grid_forget()
yourpassword.grid_forget()
yourpassword1.grid_forget()
yournumber.grid_forget()
yournumber1.grid_forget()
panel.grid_forget()
toolbar.grid_forget()
yes.grid_forget()
no.grid_forget()
entry.delete(0,END)
entry1.delete(0,END)
entry2.delete(0,END)
Titlemsg.grid( row=7, pady=25, sticky=N+S+E+W)
startpic.grid( row=10,pady=25, )
Head.grid( row=14, pady=25, columnspan=2, sticky=N+S+E+W)
toolbar.grid( row=21, )
end.grid(column =3, row=1, sticky=N+S+E+W)
begin.grid(column =2, row=1, sticky=N+S+E+W)
def start():
#entry.destroy()
#entry1.destroy()
#entry2.destroy()
toolbar.grid_forget()
Titlemsg.grid_forget()
begin.grid_forget()
Head.grid_forget()
startpic.grid_forget()
web.grid(row=3, column=0, sticky= W+E)
entry.grid( row=3, column=1, padx=50)
passw.grid(row=10, column=0)
Notice1.grid(row=4, sticky=N+S+E+W, columnspan=2)
entry1.grid(row=10, column=1)
Notice.grid(row=11,column=0, columnspan=2,)
secret.grid(row=13, column=0)
entry2.grid( row=13, column=1)
Notice2.grid( row=14,column=0, columnspan=2,)
panel.grid(row=20,columnspan=2, pady=70)
confirm.grid(column =1, row=1)
reset.grid(column =2, row=1)
end.grid(column =3, row=1)
toolbar.grid(row=21, column=0, columnspan=2)
Titlemsg.grid(row=0, column=0, columnspan=2, sticky=E+W)
def Reset():
entry.delete(0,END)
entry1.delete(0,END)
entry2.delete(0,END)
def clear_text():
#entry.destroy()
#entry1.destroy()
#entry2.destroy()
panel.grid_forget()
entry.grid_forget()
entry1.grid_forget()
entry2.grid_forget()
web.grid_forget()
Notice.grid_forget()
passw.grid_forget()
secret.grid_forget()
Notice1.grid_forget()
Notice2.grid_forget()
confirm.grid_forget()
reset.grid_forget()
toolbar.grid_forget()
Titlemsg.grid_forget()
Titlemsg.grid(row=0, column=0, columnspan=2, sticky=E+W)
correct.grid(row=1, column=0, columnspan=2, sticky=E+W)
yourwebsite.grid(row=2,column=0,sticky=E+W, pady=5)
website1.grid(row=2, column=1, padx=65,sticky=E+W, pady=5)
yourpassword.grid(row=4, column=0,sticky=E+W, pady=5)
yourpassword1.grid(row=4, column=1, padx=65,sticky=E+W, pady=5)
yournumber.grid(row=6, column=0,sticky=E+W, pady=5)
yournumber1.grid(row=6, column=1, padx=65,sticky=E+W, pady=5)
panel.grid(row=8, column=0, columnspan=2, pady=50)
toolbar.grid(row=10, column=0, columnspan=2)
yes.grid(column =1, row=1)
no.grid(column =2, row=1)
def popup():
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Your password is:", font=Body1, fg="red", bg="#ffefd5")
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
pwd= Label(top, font=Body2, text="password", bg="#ffefd5", fg= "#00009C", ) #textvariable = newpassword ,
pwd.grid(row= 2, column=1,sticky=E+W,padx=15)
button = Button(top, text="OK", command=top.destroy, relief=RAISED )
button.grid(column =0,columnspan=2, row=4, sticky=N+S+E+W)
def helpmsg():
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Koala series 1.0 - Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
pwd= Label(top, font=Body, text="Free software to help you keep your acounts safe", bg="#ffefd5")
pwd.grid(row= 1,sticky=E+W,)
Titlems = Label(top, text="Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
Titlems.grid( row=0, pady=25, sticky=N+S+E+W)
button = Button(top, text="OK", command=top.destroy, relief=RAISED )
button.grid(column =0,columnspan=2, row=4, sticky=N+S+E+W)
max_len = 5
def on_write(*args):
s = website.get()
if len(s) > max_len:
website.set(s[:max_len])
website.trace_variable("w", on_write)
max_len1 = 5
def on_write(*args):
s = passwordvar.get()
if len(s) > max_len1:
passwordvar.set(s[:max_len1])
passwordvar.trace_variable("w", on_write)
max_len2 = 1
def on_write(*args):
s = numbervar.get()
if len(s) > max_len2:
numbervar.set(s[:max_len2])
numbervar.trace_variable("w", on_write)
toolbar = Frame(root)
reset = Button(toolbar, text="Reset", width=6, command=Reset, cursor="cross", relief=RAISED, takefocus=True )
end = Button(toolbar, text="Quit" ,command=root.destroy, relief=RAISED, cursor="X_cursor", takefocus=True)
end.grid(column =3, row=1, sticky=N+S+E+W)
begin = Button(toolbar, text="Start Encrypting", command=start, relief=RAISED, cursor="star",takefocus=True )
begin.grid(column =2, row=1, sticky=N+S+E+W)
confirm = Button(toolbar, text="Next", command =clear_text, cursor="star", relief=RAISED,takefocus=True )
yes = Button(toolbar, text="Yes", command =popup, cursor="star", relief=RAISED,takefocus=True )
no = Button(toolbar, text="No", command =restart, cursor="pirate", relief=RAISED, takefocus=True )
toolbar.grid( row=21, )
menu = Menu(root)
root.config(menu=menu)
filemenu = Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Restart", command=restart)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=root.destroy)
helpmenu = Menu(menu)
menu.add_cascade(label="Help", menu=helpmenu, )
helpmenu.add_command(label="About...", command=helpmsg)
app = root
root.mainloop()
# add functionality, fix validation
To restrict the type/number of characters that can be typed into an entry widget, you can use the entry validatecommand. Here is an example to allow only letters and another one to restrict the entry to 4 digits:
from tkinter import Tk, Entry, Label
def only_letters(action, char):
if action == "1":
# a character is inserted (deletion is 0) allow the insertion
# only if the inserted character char is a letter
return char.isalpha()
else:
# allow deletion
return True
def only_numbers_max_4(action, new_text):
if action == "1":
return new_text.isdigit() and len(new_text) <= 4
else:
return True
root = Tk()
# register validate commands
validate_letter = root.register(only_letters)
validate_nb = root.register(only_numbers_max_4)
Label(root, text="Only letters: ").grid(row=0, column=0)
e1 = Entry(root, validate="key", validatecommand=(validate_letter, '%d', '%S'))
# %d is the action code and %S the inserted/deleted character
e1.grid(row=0, column=1)
Label(root, text="Only numbers, at most 4: ").grid(row=1, column=0)
e2 = Entry(root, validate="key", validatecommand=(validate_nb, '%d', '%P'))
# %P is the new content of the entry after the modification
e2.grid(row=1, column=1)
root.mainloop()
For more details on entry validation, see http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html

Categories

Resources