How to pop up an on screen keyboard to enter some data in an entry gadget in tkinter

白昼怎懂夜的黑 提交于 2021-01-25 20:46:46

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!