繁体   English   中英

如何使用触摸屏显示调用和关闭 Tkinter 制作的虚拟键盘

[英]How to call and close a virtual keyboard made by Tkinter using touchscreen display

我在打开和关闭用 Tkinter 制作的虚拟键盘时遇到问题。 我正在创建一个 GUI,用户将使用触摸屏显示器浏览它,并且用户需要输入条目。

我试过var_name.bind('FocusIn', callback)来调用虚拟键盘和var_name.bind('FocusOut',callback)来关闭虚拟键盘但是当我同时使用虚拟键盘时,虚拟键盘正在打开然后立即关闭.

我希望你们能帮助我这是我的代码:

import tkinter as tk

def select(entry, value, event):
    focused_entry.insert("end", event)
    pyautogui.press(event)
    global uppercase
    uppercase = False

    if value == "Space":
        value = ' '
    elif value == 'Enter':
        value = '\n'
    elif value == 'Tab':
        value = '\t'

    if value == "Backspace":
        if isinstance(entry, tk.Entry):
            entry.delete(len(entry.get())-1, 'end')
        #elif isinstance(entry, tk.Text):
        else: # tk.Text
            entry.delete('end - 2c', 'end')
    elif value in ('Caps Lock', 'Shift'):
        uppercase = not uppercase # change True to False, or False to True
    else:
        if uppercase:
            value = value.upper()
        entry.insert('end', value)
    return

def create(root, entry):
    alphabets = [
        ['`','1','2','3','4','5','6','7','8','9','0','-','=','Backspace'],
        ['Tab','q','w','e','r','t','y','u','i','o','p','[',']',"\\"],
        ['Caps Lock','a','s','d','f','g','h','j','k','l',';',"'",'Enter'],
        ['Shift','z','x','c','v','b','n','m',',','.','/','Shift'],
        ['Space']
    ]    

    global window
    window = tk.Toplevel(root)
    window.configure(background="cornflowerblue")
    window.geometry("+0+483")
    window.wm_attributes("-alpha", 0.7)

    for y, row in enumerate(alphabets):

        x = 0

        #for x, text in enumerate(row):
        for text in row:

            if text in ('Enter', 'Shift'):
                width = 18
                columnspan = 2
            elif text == 'Space':
                width = 124
                columnspan = 16
            elif text == 'Backspace':
                width = 10
                columnspan = 1
            elif text == '\\':
                width = 10
                columnspan = 1
            elif text == 'Tab':
                width = 10
                columnspan = 1
            elif text == '`':
                width = 10
                columnspan = 1
            elif text == 'Caps Lock':
                width = 10
                columnspan = 1
            else:                
                width = 4
                columnspan = 1

            tk.Button(window, text=text, width=width, 
                      command=lambda value=text: select(entry, value),
                      padx=3, pady=3, bd=12, bg="black", fg="white", takefocus = False
                     ).grid(row=y, column=x, columnspan=columnspan)

            x+= columnspan


# --- main ---

def remember_focus(event):
    global focused_entry
    focused_entry = event.widget

if __name__ == '__main__':
    root = tk.Tk()
    root.title('Test Keyboard')

    label = tk.Label(root, text='Test Keyboard')
    label.grid(row=0, column=0, columnspan=2)

    entry1 = tk.Entry(root)
    entry1.grid(row=1, column=0, sticky='news')
    entry1.bind("<FocusIn>", remember_focus)

    entry2 = tk.Entry(root)
    entry2.grid(row=2, column=0, sticky='news')
    entry2.bind("<FocusIn>", remember_focus)

    text1 = tk.Text(root)
    text1.grid(row=3, column=0, sticky='news')
    text1.bind("<FocusIn>", remember_focus)

    root.mainloop()

谢谢@furas 先生帮助我创建虚拟键盘。 我编辑了代码并在此处尝试了 Bryan Oakley 的回答Tkinter 检查哪个条目最后具有焦点

问题:使用触摸屏显示调用和关闭虚拟键盘

而是调用和关闭,实例化虚拟键盘一次,并使用Toplevel methodes .deiconify().withdraw()

不要将事件'<FocusIn>'绑定到每个输入小部件,使用bind_all(... . 绑定到应用程序级别


参考


核心点

  • 使用.bind_all('<FocusIn>', ... to .deiconify()
  • 使用.bind_all('<Button-1>', ... to .withdraw()
# VKeyboard.py
import tkinter as tk


class VKeyboard(tk.Toplevel):
    def __init__(self, parent):
        super().__init__(parent)
        # Don't show the 'Toplevel' at instantiation
        super().withdraw()
                
        self.create()
        
        # Process all application == parent events
        parent.bind_all('<FocusIn>', self.on_event, add='+')
        parent.bind_all('<Button-1>', self.on_event, add='+')
    
    def on_event(self, event):
        w = event.widget
        
        # Don't process the own Button
        if w.master is not self:
            w_class_name = w.winfo_class()
            
            if w_class_name in ('Entry',):
                if self.state() == 'withdrawn':
                    self.deiconify()
                
                self.entry = w
            
            elif w_class_name in ('Button',):
                super().withdraw()
                w.focus_force()

    def create(self):
        # define the virtual keyboard `tk.Button`
        pass

用法

import tkinter as tk
from VKeyboard import VKeyboard


class Kiosk(tk.Tk):
    def __init__(self):
        super().__init__()
        
        VKeyboard(self)

        tk.Entry(root).grid()
        tk.Button(root, text='withdraw').grid()
                 

if __name__ == "__main__":
    Kiosk().mainloop()

用 Python 测试:3.5 - 'TclVersion':8.6 'TkVersion':8.6

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM