问题
I have a tkinter GUI app. I am using a raspberry pi with a touch screen. Raspberry pi's virtual keyboard creates many chaos. So I was thinking of an automatic keypad. There are some entry fields. Is it possible to do something like when the user clicks the entry field, a key pad (just numbers) pop up and then the user can use that key pad to enter values in entry field. I just need numbers from 0 to 9 and (.). Is it even possible to do it in tkinter? Any suggestions?
import tkinter as tk
root = tk.Tk()
root.geometry('600x400')
container_1 = tk.Frame(root, borderwidth=2, relief="solid")
set_1 = tk.Label(container_1, text = "min Current")
set_1.grid(row=3, column=9)
set_2 = tk.Label(container_1, text = "max Current")
set_2.grid(row=4, column=9)
enter_set_1 =tk.Entry(container_1, width=12) #entry fields, need a keypad here
enter_set_1.grid(row=3, column=10)
enter_set_2 =tk.Entry(container_1, width=12)
enter_set_2.grid(row=4, column=10)
container_1.pack(side="left", expand=True, fill="x", padx=10, pady=10)
root.mainloop()
回答1:
This simple example uses Button
near Entry
to open Frame
with keypad
. It also assigns Entry
to variable target
which buttons use to put text in correct Entry
.
It uses place
to put keypad
in center of window.
It would need more work to open keypad when you click on Entry
and display it nearer Entry
.
Using Class
you could create widget Keypad
.
import tkinter as tk
def create_keypad(root):
keypad = tk.Frame(root)
for y in range(3):
for x in range(3):
val = y*3 + x
text = str(val)
b = tk.Button(keypad, text=text, command=lambda txt=text:insert_text(txt))
b.grid(row=y, column=x, sticky='news')
x = tk.Button(keypad, text='Hide', command=hide_keypad)
x.grid(row=10, column=0, columnspan=3, sticky='news')
return keypad
def insert_text(text):
target.insert('end', text)
def show_keypad(widget):
global target
target = widget
keypad.place(relx=0.5, rely=0.5, anchor='c')
def hide_keypad():
global taget
target = None
keypad.place_forget()
root = tk.Tk()
root.geometry('600x400')
keypad = create_keypad(root)
target = None
f = tk.Frame(root)
f.pack()
e1 = tk.Entry(f)
e1.grid(row=0, column=0)
b1 = tk.Button(f, text='Keypad', command=lambda:show_keypad(e1))
b1.grid(row=0, column=1)
e2 = tk.Entry(f)
e2.grid(row=1, column=0)
b2 = tk.Button(f, text='Keypad', command=lambda:show_keypad(e2))
b2.grid(row=1, column=1)
root.mainloop()
EDIT: I put code in Class so now it is widget. It has buttons "Clear", "Backspace", and memory "Copy", "Paste" but it doesn't use clipboard.
import tkinter as tk
# --- classes ---
class Keypad(tk.Frame):
cells = [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '.', '-'],
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.target = None
self.memory = ''
for y, row in enumerate(self.cells):
for x, item in enumerate(row):
b = tk.Button(self, text=item, command=lambda text=item:self.append(text))
b.grid(row=y, column=x, sticky='news')
x = tk.Button(self, text='Backspace', command=self.backspace)
x.grid(row=0, column=10, sticky='news')
x = tk.Button(self, text='Clear', command=self.clear)
x.grid(row=1, column=10, sticky='news')
x = tk.Button(self, text='Copy', command=self.copy)
x.grid(row=9, column=0, sticky='news', columnspan='3')
x = tk.Button(self, text='Paste', command=self.paste)
x.grid(row=9, column=10, sticky='news')
self.label = tk.Label(self, text='memory:')
self.label.grid(row=8, column=0, columnspan=11, sticky='news')
x = tk.Button(self, text='Hide', command=self.hide)
x.grid(row=10, column=0, columnspan=11, sticky='news')
def get(self):
if self.target:
return self.target.get()
def append(self, text):
if self.target:
self.target.insert('end', text)
def clear(self):
if self.target:
self.target.delete(0, 'end')
def backspace(self):
if self.target:
text = self.get()
text = text[:-1]
self.clear()
self.append(text)
def copy(self):
#TODO: copy to clipboad
if self.target:
self.memory = self.get()
self.label['text'] = 'memory: ' + self.memory
print(self.memory)
def paste(self):
#TODO: copy from clipboad
if self.target:
self.append(self.memory)
def show(self, entry):
self.target = entry
self.place(relx=0.5, rely=0.5, anchor='c')
def hide(self):
self.target = None
self.place_forget()
# --- main ---
root = tk.Tk()
root.geometry('600x400')
keypad = Keypad(root)
f = tk.Frame(root)
f.pack()
e1 = tk.Entry(f)
e1.grid(row=0, column=0, sticky='news')
b1 = tk.Button(f, text='Keypad', command=lambda:keypad.show(e1))
b1.grid(row=0, column=1, sticky='news')
e2 = tk.Entry(f)
e2.grid(row=1, column=0, sticky='news')
b2 = tk.Button(f, text='Keypad', command=lambda:keypad.show(e2))
b2.grid(row=1, column=1, sticky='news')
root.mainloop()
回答2:
#method to add backspace button to above solution
backspacebtn= tkinter.Button(keypad, text='Back', command=lambda:fn_back())
backspacebtn.grid(row=1, columnspan=1)
def fn_back():
global target
val = target.get()
new_val= val[:-1]
target.delete(0,tk.END)
target.insert(0,new_val)
来源:https://stackoverflow.com/questions/57161644/how-to-pop-up-an-on-screen-keyboard-to-enter-some-data-in-an-entry-gadget-in-tki