[英]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
创建一个绑定来处理应用程序级别的事件。
bind_all(sequence=None, func=None, add=None)
将事件绑定添加到应用程序级别。
核心点:
.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.