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

2024-04-19

我在打开和关闭使用 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 检查哪个条目最后获得焦点 https://stackoverflow.com/questions/45237883/tkinter-check-which-entry-last-had-focus


Question:使用触摸屏调用和关闭虚拟键盘

代替调用并关闭,实例化您的虚拟键盘一次并使用Toplevel方法.deiconify() and .withdraw().

不绑定事件'<FocusIn>'到每个输入小部件,绑定到应用层 using bind_all(....


参考:

  • 事件和绑定 - 部分:实例和类绑定 http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm

    Use bind_all创建一个绑定来在应用程序级别处理事件。

  • bind_all(sequence=None, func=None, add=None) http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.bind_all-method

    将事件绑定添加到应用程序级别。


核心点:

  • Use .bind_all('<FocusIn>', ... to .deiconify()
  • Use .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

Usage

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用触摸屏调用和关闭 Tkinter 制作的虚拟键盘 的相关文章

  • x 或 y:可接受的习语,还是混淆?

    我必须从可能为 None 的变量中提取值 并考虑一些默认值 我首先写了这段代码 if self maxTiles is None maxX maxY 2 2 else maxX maxY self maxTiles 然后我意识到我可以将其缩
  • 不要在异常堆栈中显示 Python raise-line

    当我在 Python 库中引发自己的异常时 异常堆栈将引发行本身显示为堆栈的最后一项 这显然不是一个错误 在概念上是正确的 但是当您在外部使用代码 例如作为模块 时 它会将重点放在对调试无用的东西上 有没有办法避免这种情况并强制 Pytho
  • Python中的键盘可中断阻塞队列

    It seems import Queue Queue Queue get timeout 10 键盘可中断 ctrl c 而 import Queue Queue Queue get 不是 我总是可以创建一个循环 import Queue
  • 将 KB/MB/GB 等字符串解析为数值

    为了不发明自行车 我想知道是否有任何库能够将大小字符串 MB KB TB MiB KiB 等 的各种表示形式解析为基于数字字节的值 ActiveState Receipes 有一个示例here http code activestate c
  • 使用自定义元素类在 Python 中解析 xml

    我想使用 Python 的 xml etree ElementTree 模块解析 xml 文档 但是 我希望生成的树对象中的所有元素都具有我定义的一些类方法 这建议创建我自己的 Python 元素类的子类 但我无法告诉解析器在解析时使用我自
  • 如何在Python中通过URL下载Azure Blob存储文件?

    我正在尝试从我的存储帐户下载 Azure Blob 存储文件 为此 我检查了 URL 是什么 并且正在执行以下操作 with urllib request urlopen
  • 为什么我在 Python 中收到“连接被拒绝”错误? (插座)

    我是套接字新手 请原谅我完全缺乏理解 我有一个服务器脚本 server py usr bin python import socket import the socket module s socket socket Create a so
  • 混淆矩阵错误“分类指标无法处理多标签指标和多类目标的混合”

    我得到了 Classification metrics can t handle a mix of multilabel indicator and multiclass targets 当我尝试使用混淆矩阵时出错 我正在做我的第一个深度学
  • scipy 的 curve_fit 函数的尺寸问题

    我对 python 中的曲线拟合以及一般的 python 都很陌生 目前 我正在尝试使用 scipy 中的 curve fit 模块来拟合 4 个光谱峰 简而言之 我的文本文件中有两列数据 所以我的第一步是将数据导入到两个数组中 一个包含
  • Python lmfit:拟合 2D 模型

    我正在尝试将二维高斯拟合到一些灰度图像数据 该数据由一个二维数组给出 lmfit 库实现了一个易于使用的模型类 它应该能够做到这一点 不幸的是文档 http lmfit github io lmfit py model html http
  • 如何在 PyCharm 中启用 flake8 的自动代码格式化

    我使用 Tox 运行单元测试 并使用 flake8 命令检查代码格式错误 每次我在 PyCharm 中编码时 我都会运行 tox 然后意识到我有一堆烦人的格式错误 我必须返回并手动修复 我希望 PyCharm 自动格式化代码 根据 flak
  • 使用底图和Python在地图中绘制海洋

    我正在绘制此处提供的 netCDF 文件 https goo gl QyUI4J https goo gl QyUI4J Using the code below the map looks like this 然而 我希望海洋是白色的 更
  • 有没有办法在Python中调用子类定义的方法?

    The init 方法定义了创建类的实例时要执行的操作 创建子类时我可以做类似的事情吗 假设我有抽象类Entity class Entity def onsubclasscreation cls for var in cls annotat
  • python中不规则点之间的坐标列表

    想象一下 我们为 x 和 y 随机选择两个介于 0 到 100 之间的点 例如 95 7 35 6 现在使用简单的 pygame draw line 函数 我们可以轻松地在这些点之间绘制一条没有任何间隙的线 我的问题是 我们如何找到两点之间
  • 为什么这个记忆器适用于递归函数?

    我不明白为什么下面的代码是这样的fib以线性而非指数时间运行 def memoize obj Memoization decorator from PythonDecoratorLibrary Ignores kwargs cache ob
  • 对二进制数的字符串表示进行按位运算 python 2.7

    我想对二进制数的两个字符串表示执行按位或 但我不知道如何将字符串转换为原始二进制 a 010110 b 100000 a b 应该产生 110110 然后我想计算 on 位的数量 这应该返回 4 您可以使用内置的将字符串转换为二进制int
  • Mac OS 上的 pybluez 安装错误

    我尝试安装pybluez使用以下命令 pip install pybluez sudo easy install pybluez 但对于这两个命令我最终都会出错 环境 Mac OSX 10 9 1 Python 2 7 点日志 cc fno
  • 帮助我在 Python 中实现反向传播

    EDIT2 新的训练集 Inputs 0 0 0 0 0 0 1 0 0 0 2 0 0 0 3 0 0 0 4 0 1 0 0 0 1 0 1 0 1 0 2 0 1 0 3 0 1 0 4 0 2 0 0 0 2 0 1 0 2 0 2
  • python字符串包含双引号字符

    我的输入字符串由字符组成 包括双引号和单引号 和 B SS JU PQ AD DDSFD ABD E J 但是 当我从文本文件打开上述输入并打印它时 第三行中的双引号 被打印为 xe2 x80 x9d 我的目标是进行简单的字符计数 B 2
  • 如何在Python中检查元组是否包含元素?

    我试图找到可用的方法 但找不到 没有contains 我应该使用index 我只想知道该项目是否存在 不需要它的索引 You use in if element in thetuple whatever you want to do

随机推荐