python - 如何获得 TkInter GUI(不是 shell 提示符)以监听来自/dev/stdin 的输入

标签 python multithreading user-interface tkinter

我正在编写一个带有 GUI 的 Python 程序,用于监听呈现的 RFID token (使用模拟键盘输入的 USB 读取器)。我遇到的问题是,如果我从中启动脚本的终端具有焦点,则键盘/RFID 输入只会被监听和执行。

如果 GUI 有焦点,所有输入都会被忽略,但当终端有焦点时,它工作正常,甚至会向 GUI 和 shell 发送更新。我试过在 GUI 上绘制一个文本输入框,但没有成功。

我想知道这是否与它需要如何使用多线程、队列甚至进程有关 - 谁能帮助我更好地理解它?

代码如下,在此先感谢!

#!/usr/bin/env python3
import sys
import MySQLdb

try:
    # python 2
    import Tkinter as tk
    import ttk
except ImportError:
    # python 3
    import tkinter as tk
    from tkinter import ttk

from threading import Thread

class Fullscreen_Window:

def __init__(self):
    self.tk = tk.Tk()
    self.tk.title("Listening for RFID token...")
    self.frame = tk.Frame(self.tk)
    self.frame.pack()

    self.tk.attributes('-zoomed', True)
    self.state = False
    self.tk.bind("<F11>", self.toggle_fullscreen)
    self.tk.bind("<Escape>", self.end_fullscreen)
    self.tk.config(cursor="none")

    t = Thread(target=self.listen_rfid)
    t.daemon = True
    t.start()

def toggle_fullscreen(self, event=None):
    self.state = not self.state  # Just toggling the boolean
    self.tk.attributes("-fullscreen", self.state)
    return "break"

def end_fullscreen(self, event=None):
    self.state = False
    self.tk.attributes("-fullscreen", False)
    return "break"

def listen_rfid(self):
    dbHost = 'localhost'
    dbName = 'python'
    dbUser = 'python'
    dbPass = 'PASSWORD'

    dbConnection = MySQLdb.connect(host=dbHost, user=dbUser, passwd=dbPass, db=dbName)
    cur = dbConnection.cursor(MySQLdb.cursors.DictCursor)

    with open('/dev/stdin', 'r') as tty:
        while True:
            RFID_input = tty.readline().rstrip()
            cur.execute("SELECT * FROM access_list WHERE rfid_code = '%s'" % (RFID_input))

            if cur.rowcount != 1:
                print("ACCESS DENIED")
                ttk.Label(self.tk, text="ACCESS DENIED").pack()
            else:
                user_info = cur.fetchone()
                print("Welcome %s!!" % (user_info['name']))
                ttk.Label(self.tk, text="Welcome %s!!" % (user_info['name'])).pack()
    tty.close()


if __name__ == '__main__':
w = Fullscreen_Window()
w.tk.mainloop()

最佳答案

经过一番摸索之后,我再次找到 this thread 并正确地重新阅读它,然后意识到它包含了我想要的答案,尽管我需要做一点点工作。

我的 listen_rfid 函数现在看起来像下面的代码。希望它对遇到我的问题的任何人都有用!

关键是查看 /dev/input/by-id 并找到你的设备,会有一个符号链接(symbolic link)(至少在我的 Raspbian 安装上有)到更优雅的东西,比如,在我的例子中,“/event0”——如下所示)。然后您可以使用 python-evdev 读取它。

如果您没有 python-evdev,只需使用 sudo pip install evdev 安装即可

这是工作代码:

def listen_rfid(self):
    dbHost = 'localhost'
    dbName = 'python'
    dbUser = 'python'
    dbPass = 'PASSWORD'

    dbConnection = MySQLdb.connect(host=dbHost, user=dbUser, passwd=dbPass, db=dbName) # ToDo: This needs some error handling for if MySQL has gone away, and reconnect.
    cur = dbConnection.cursor(MySQLdb.cursors.DictCursor)

    from evdev import InputDevice
    from select import select

    keys = "X^1234567890XXXXqwertzuiopXXXXasdfghjklXXXXXyxcvbnmXXXXXXXXXXXXXXXXXXXXXXX"
    dev = InputDevice('/dev/input/event0')
    rfid_presented = ""

    while True:
       r,w,x = select([dev], [], [])
       for event in dev.read():
            if event.type==1 and event.value==1:
                    if event.code==28:
                        #print("RFID: " + str(rfid_presented))

                        cur.execute("SELECT * FROM access_list WHERE rfid_code = '%s'" % (rfid_presented))

                        if cur.rowcount != 1:
                            #print("ACCESS DENIED")
                            ttk.Label(self.tk, text="ACCESS DENIED").pack()
                        else:
                            user_info = cur.fetchone()
                            #print("Welcome %s!!" % (user_info['name']))
                            ttk.Label(self.tk, text="Welcome %s!!" % (user_info['name'])).pack()

                        rfid_presented = ""
                    else:
                        rfid_presented += keys[ event.code ]

关于python - 如何获得 TkInter GUI(不是 shell 提示符)以监听来自/dev/stdin 的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44720852/

相关文章:

html - inline-block 出现不必要的滚动条

java gui图像问题: doesn't display in the background

java - 如何通过单独的 Java 进程访问 Windows GUI 文件菜单?

python - Bash 脚本还有什么用处吗?

python - 通过 pyusb 从 USB 鼠标(单芯片,ADNS-2700)获取图像

python - 在Docker上安装detectron2软件包

Python 2.3 多处理

python - 子线程内的多处理

python - 处理具有作为参数给定的大量属性的对象的正确/Pythonic 方法

java - 为什么阻塞 IO API 在早期的 Java 中不是问题?