首页 > 解决方案 > 停止 ttk.Entry() 读取键盘

问题描述

环境:macOS Catalina、Python 3.7.4、Tcl/Tk 8.6.9、VSC 1.39.1

我有一种情况,我使用条形码/二维码扫描仪向 ttk.Entry() 方法提供字符串,然后触发一个函数。

操作系统将阅读器视为 HID 键盘,因此来自 QR 码的文本由我在代码执行期间关注的 ttk.Entry() 小部件接收。我已将小部件绑定到键,因为扫描仪会在文本字符串的末尾发送一个 cr/lf,它可以根据需要工作。

但是,我遇到了一个问题,如果 qr 码在扫描仪上停留的时间过长,它将重新扫描 qr 码,并且小部件再次接收到 qr 码文本,然后再次对其进行处理。

我尝试在函数中禁用 ttk.Entry() ,删除小部件内容,并删除焦点无济于事。即使小部件被禁用并且没有焦点,我看到的行为也会发生,如果扫描仪在函数执行时重新扫描二维码,它仍然会获取输入并再次执行函数。

在第一个示例中,我只是尝试禁用小部件,但这不起作用。小部件在功能中仍会获得以后的扫描。

# test-ttk-entry1.py

import time
import tkinter as tk
from tkinter import StringVar, ttk

root = tk.Tk()

def print_text(event):
    global kbEntry
    textValue = kbEntry.get()
    kbEntry.configure(state="disabled")
    time.sleep(2) # Add in a delay to allow for repeat scan
    print(textValue)
    time.sleep(2) # Add in a delay to allow for repeat scan
    kbEntry.configure(state="active")

kbText = StringVar()
kbEntry = ttk.Entry(root, width=10, textvariable=kbText)
kbEntry.bind("<Return>", print_text)
kbEntry.pack()
kbEntry.focus_set()

root.mainloop()

第二次尝试是禁用条目小部件,并在使其再次处于活动状态时删除该字段中的文本。

# test-ttk-entry2.py

import time
import tkinter as tk
from tkinter import END, StringVar, ttk

root = tk.Tk()

def print_text(event):
    global kbEntry
    textValue = kbEntry.get()
    kbEntry.delete(0, END)
    kbEntry.configure(state="disabled")
    time.sleep(2) # Add in a delay to allow for repeat scan
    print(textValue)
    time.sleep(2) # Add in a delay to allow for repeat scan
    kbEntry.configure(state="active")
    kbEntry.delete(0, END)

kbText = StringVar()
kbEntry = ttk.Entry(root, width=10, textvariable=kbText)
kbEntry.bind("<Return>", print_text)
kbEntry.pack()
kbEntry.focus_set()

root.mainloop()

最后,我正在阅读有关从小部件获取焦点并将焦点赋予根窗口的信息,所以我添加了它,它仍然会多次打印到控制台,就像 ttk.Entry() 小部件正在读取键盘缓冲区一样. 奇怪的是,当它们被禁用时,小部件似乎通常不会响应对方法的任何调用,但似乎 ttk.Entry() 小部件的属性/属性(如果我的 OOP 术语不正确,请原谅)可以被操纵禁用时。

# test-ttk-entry2.py

import time
import tkinter as tk
from tkinter import END, StringVar, ttk

root = tk.Tk()

def print_text(event):
    global kbEntry
    textValue = kbEntry.get()
    kbEntry.delete(0, END)
    kbEntry.configure(state="disabled")
    root.focus_set()
    time.sleep(2) # Add in a delay to allow for repeat scan
    print(textValue)
    time.sleep(2) # Add in a delay to allow for repeat scan
    kbEntry.configure(state="active")
    kbEntry.delete(0, END)
    kbEntry.focus_set()

kbText = StringVar()
kbEntry = ttk.Entry(root, width=10, textvariable=kbText)
kbEntry.bind("<Return>", print_text)
kbEntry.pack()
kbEntry.focus_set()

root.mainloop()

那么如何防止 ttk.Entry() 小部件在我的函数执行时接受来自 HID/键盘设备的任何输入?

标签: python-3.xtkintertkinter-entry

解决方案


由于我无法找到以编程方式暂时禁用 .Entry() 小部件以使其无法读取连续输入的方法,因此我提出了以下解决方案:

# test-ttk-entry2.py

import time
import tkinter as tk
from tkinter import END, StringVar, ttk

root = tk.Tk()
tempStr = "" # Global temporary string variable to trip repeated scans

def print_text(event):

    global tempStr

    textValue = kbEntry.get()
    if tempStr == textValue:
        kbEntry.delete(0, END)
        print ("Duplicate scan")
        return
    tempStr = textValue
    kbEntry.delete(0, END)
    print(textValue)
    time.sleep(3) # Simulate the time it takes for the function to complete

kbEntry = ttk.Entry(root, width=10)
kbEntry.bind("<Return>", print_text)
kbEntry.grid(row=0, column=0, padx=10, pady=10)
kbEntry.focus_set()

root.mainloop()

推荐阅读