【问题标题】:stop ttk.Entry() from reading keyboard停止 ttk.Entry() 读取键盘
【发布时间】:2019-10-15 17:25:31
【问题描述】:

环境: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/键盘设备的任何输入?

【问题讨论】:

  • 如果我在函数内对 kbEntry.get() 执行后续调用,则缓冲区为空。但是一旦该功能完成,Entry 小部件就会开始对 QR 码进行后续扫描,就像它在缓冲区中等待并且 Entry 小部件看到它并重新触发事件一样。
  • 您可以通过在输入字段中快速输入“1234” 来查看此操作。这也需要是非阻塞的。
  • 我一直在搞乱 .pack_forget() 试图阻止 .Entry() 小部件接收多个(重复)条目,但到目前为止,这并不是最好的。我想我会编写我的回调来保存一个全局字符串变量,并在连续调用时检查它是否存在重复条目并忽略额外的条目。

标签: python-3.x tkinter tkinter-entry


【解决方案1】:

由于我无法找到以编程方式暂时禁用 .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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-01
    • 2021-04-21
    • 2016-06-15
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多