我正在编写一个带有 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/