TkInter Frame doesn't load if another function is called
我正在编写一个python程序,它监听RFID输入,并且只在提供有效令牌时运行。这个程序还有一个图形用户界面,我想用tkinter构建它。
这两个部分的谜题单独工作都很好,但就目前而言,我似乎可以选择其中一个或另一个-但不能同时选择两者!我可以很好地绘制我的tkinter窗口,但是如果我调用函数开始监听RFID输入,那么当该位运行正常并工作时…没有GUI。
代码如下。到目前为止,您可以看到我在终端上打印的调试工作…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | #!/usr/bin/env python3 import sys import MySQLdb if sys.version_info[0] == 2: from Tkinter import * import Tkinter as ttk else: from tkinter import * import tkinter as ttk class Fullscreen_Window: def __init__(self): self.tk = Tk() self.frame = Frame(self.tk) self.frame.pack() ttk.Button(self.tk, text="hello world").pack() self.tk.attributes('-zoomed', True) self.state = False self.tk.bind("<F11>", self.toggle_fullscreen) self.tk.bind("<Escape>", self.end_fullscreen) print("init running") self.listen_rfid() # Commenting this out makes the GUI appear, uncommenting means no GUI :( def toggle_fullscreen(self, event=None): self.state = not self.state # Just toggling the boolean self.tk.attributes("-fullscreen", self.state) print("Toggling") return"break" def end_fullscreen(self, event=None): self.state = False self.tk.attributes("-fullscreen", False) return"break" def listen_rfid(self): print("Main loop running") 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") else: user_info = cur.fetchone() print("Welcome %s!!" % (user_info['name'])) tty.close() listen_rfid() if __name__ == '__main__': w = Fullscreen_Window() w.tk.mainloop() |
我肯定这是很简单的事情,但因为我是一个python/tkintern00b,它打败了我,我都完成了谷歌搜索。感谢您的帮助:)
tkinter(以及所有的gui)有一个称为mainloop的无限循环,它使gui保持活动和响应。当您进行另一个无限循环(
1 2 3 4 | from threading import Thread t = Thread(target=self.listen_rfid) t.daemon = True # this line tells the thread to quit if the GUI (master thread) quits. t.start() |
编辑:顺便说一句,你的进口很糟糕。""ttk"是tkinter的一个子集,而不是别名,别名"tk"通常用于tkinter,通配符导入很糟糕,应该避免。这就是您的tkinter导入产品的外观:
1 2 3 4 5 6 7 8 | try: # python 2 import Tkinter as tk import ttk except ImportError: # python 3 import tkinter as tk from tkinter import ttk |
然后使用适当的前缀:
1 2 | self.tk = tk.Tk() self.frame = tk.Frame(self.tk) |
您应该使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #!/usr/bin/env python3 import sys import select import MySQLdb if sys.version_info[0] == 2: from Tkinter import * import Tkinter as ttk else: from tkinter import * import tkinter as ttk class Fullscreen_Window: def __init__(self): self.tk = Tk() self.frame = Frame(self.tk) self.frame.pack() ttk.Button(self.tk, text="hello world").pack() self.tk.attributes('-zoomed', True) self.state = False self.tk.bind("<F11>", self.toggle_fullscreen) self.tk.bind("<Escape>", self.end_fullscreen) print("init running") # Schedule self.listen_rfid to run after the mainloop starts self.tk.after(0, self.listen_rfid) def toggle_fullscreen(self, event=None): self.state = not self.state # Just toggling the boolean self.tk.attributes("-fullscreen", self.state) print("Toggling") return"break" def end_fullscreen(self, event=None): self.state = False self.tk.attributes("-fullscreen", False) return"break" def listen_rfid(self): print("Main loop running") 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) # readline is blocking so check that there is input # before attempting to read it. r, w, x = select.select([sys.stdin], [], [], 0) if r: # There is available input, so read a line. RFID_input = sys.stdin.readline().rstrip() cur.execute("SELECT * FROM access_list WHERE rfid_code = '%s'" % (RFID_input)) if cur.rowcount != 1: print("ACCESS DENIED") else: user_info = cur.fetchone() print("Welcome %s!!" % (user_info['name'])) # keep running every 500 milliseconds for as long as # the mainloop is active. self.tk.after(500, self.listen_rfid) if __name__ == '__main__': w = Fullscreen_Window() w.tk.mainloop() |
它每隔半秒检查一次命令行上是否有输入,并对其进行处理。