I have a program that is a group of individual "applets". Each of the applets has tk.Entry widgets that only require numeric entries and the decimal key (0-9 & .). This program runs on a Raspberry Pi with a 10" touch screen. The stock on screen keyboards (onBoard, etc.) take up way too much screen real estate, plus I only need numeric keys. So I wrote and on screen numeric keypad, but unlike the numerous YouTube calculator examples, this keypad needs to know which of the Entry widgets has focus. I'm using a list of directories to keep up with the Entry widgets and the "fields" I'll need to apply the keypad entries to. I can not come up with a way to avoid using eval() when applying the keypad entries. I suspect the answer (if there is one) lies in "nametowidget", but not sure how I'd use it here. The eval() statements are near the end of the code in the kb_entry function.
import tkinter as tk
from tkinter import messagebox
class Eval_GUI:
def __init__(self):
self.root = tk.Tk()
self.root.geometry('650x225')
self.root.title('Eval Demo')
self.allEntryFields = [] # A list of directories we'll use to apply the numeric keypad entries
# Frame 1 - A couple of Labels and Entry widgets
f1 = tk.LabelFrame(self.root,padx=5,pady=5)
f1.grid(column=0,row=0)
self.f1e1_text = tk.Label(f1,text='Frame 1 Entry 1',font=('Arial',12))
self.f1e1_text.grid(row=0,column=0)
self.f1e2_text = tk.Label(f1,text='Frame 1 Entry 2',font=('Arial',12))
self.f1e2_text.grid(row=1,column=0)
self.f1e1 = tk.StringVar() # Using StringVar because IntVar will not accept a decimal (.) and DoubleVar has a default of 0.0 which is not desired
self.f1e2 = tk.StringVar()
self.f1e1_entry=tk.Entry(f1,textvariable=self.f1e1,width='7',font=('Arial',12))
self.f1e2_entry=tk.Entry(f1,textvariable=self.f1e2,width='7',font=('Arial',12))
self.f1e1_entry.grid(row=0,column=1)
self.f1e2_entry.grid(row=1,column=1)
temp = {} # Create a temporary directory for each Entry widget
temp['focusedentry'] = '.!labelframe.!entry' # Used the print() function to find these names
temp['textvar'] = 'self.f1e1' # Will need this to get() & set() the Entry widget textvariable
temp['entrywidget'] = 'self.f1e1_entry' # Will need this to advance the cursor in the Entry widget
self.allEntryFields.append(temp) # Append the directory to the allEntryFields list
temp = {}
temp['focusedentry'] = '.!labelframe.!entry2'
temp['textvar'] = 'self.f1e2'
temp['entrywidget'] = 'self.f1e2_entry'
self.allEntryFields.append(temp)
# Frame 2 - A couple more Labels and Entry widgets
f2 = tk.LabelFrame(self.root,padx=5,pady=5)
f2.grid(column=1,row=0)
self.f2e1_text = tk.Label(f2,text='Frame 2 Entry 1',font=('Arial',12))
self.f2e1_text.grid(row=0,column=0)
self.f2e2_text = tk.Label(f2,text='Frame 2 Entry 2',font=('Arial',12))
self.f2e2_text.grid(row=1,column=0)
self.f2e1 = tk.StringVar()
self.f2e2 = tk.StringVar()
self.f2e1_entry=tk.Entry(f2,textvariable=self.f2e1,width='7',font=('Arial',12))
self.f2e2_entry=tk.Entry(f2,textvariable=self.f2e2,width='7',font=('Arial',12))
self.f2e1_entry.grid(row=0,column=1)
self.f2e2_entry.grid(row=1,column=1)
temp = {}
temp['focusedentry'] = '.!labelframe2.!entry'
temp['textvar'] = 'self.f2e1'
temp['entrywidget'] = 'self.f2e1_entry'
self.allEntryFields.append(temp)
temp = {}
temp['focusedentry'] = '.!labelframe2.!entry2'
temp['textvar'] = 'self.f2e2'
temp['entrywidget'] = 'self.f2e2_entry'
self.allEntryFields.append(temp)
# Frame 3
f3 = tk.LabelFrame(self.root,padx=5,pady=5)
f3.grid(column=2,row=0)
# Placing .grid on same line just to shorten this demo code
k7 = tk.Button(f3,text='7',bg='white',command=lambda: self.kb_entry(7) ,width=4,font=('Arial',16)).grid(row=0,column=1,padx=3,pady=3)
k8 = tk.Button(f3,text='8',bg='white',command=lambda: self.kb_entry(8) ,width=4,font=('Arial',16)).grid(row=0,column=2,padx=3,pady=3)
k9 = tk.Button(f3,text='9',bg='white',command=lambda: self.kb_entry(9) ,width=4,font=('Arial',16)).grid(row=0,column=3,padx=3,pady=3)
k4 = tk.Button(f3,text='4',bg='white',command=lambda: self.kb_entry(4) ,width=4,font=('Arial',16)).grid(row=1,column=1,padx=3,pady=3)
k5 = tk.Button(f3,text='5',bg='white',command=lambda: self.kb_entry(5) ,width=4,font=('Arial',16)).grid(row=1,column=2,padx=3,pady=3)
k6 = tk.Button(f3,text='6',bg='white',command=lambda: self.kb_entry(6) ,width=4,font=('Arial',16)).grid(row=1,column=3,padx=3,pady=3)
k1 = tk.Button(f3,text='1',bg='white',command=lambda: self.kb_entry(1) ,width=4,font=('Arial',16)).grid(row=2,column=1,padx=3,pady=3)
k2 = tk.Button(f3,text='2',bg='white',command=lambda: self.kb_entry(2) ,width=4,font=('Arial',16)).grid(row=2,column=2,padx=3,pady=3)
k3 = tk.Button(f3,text='3',bg='white',command=lambda: self.kb_entry(3) ,width=4,font=('Arial',16)).grid(row=2,column=3,padx=3,pady=3)
k0 = tk.Button(f3,text='0',bg='white',command=lambda: self.kb_entry(0) ,width=4,font=('Arial',16)).grid(row=3,column=1,padx=3,pady=3)
kd = tk.Button(f3,text='.',bg='white',command=lambda: self.kb_entry('.'),width=4,font=('Arial',16)).grid(row=3,column=2,padx=3,pady=3)
self.root.mainloop()
def kb_entry(self,the_key):
focused = str(self.root.focus_get()) # Get the Entry widget that has focus
if focused == '.':
tk.messagebox.showerror('Error','Select an Entry Field First')
else:
found = False
for i in self.allEntryFields: # Find a match in our list of directories
if i['focusedentry'] == focused:
the_tv = i['textvar']
the_en = i['entrywidget']
found = True
break
if found:
c_val = eval(the_tv).get() # Get the current value of the Focused Entry widget
n_val = c_val + str(the_key) # Concatenate the numeric keypad entry to the current value
eval(the_tv).set(n_val) # Set the value of the Focused Entry widget to the new value
eval(the_en).icursor(8) # Advance the cursor to the end of the Focused Widget (use a number greater than what you expect the Entry widget to hold
else:
tk.messagebox.showerror('Error','Unknown Entry Widget Focus ' + str(focused))
if __name__ == '__main__':
Eval_GUI()