如果调用另一个函数,则不会加载TkInter框架

我正在编写一个Python程序,用于监听RFID输入,并且只在出现有效令牌时才运行。 该程序还有一个我想用TkInter构建的GUI。

这个难题的两个部分都可以独立运作,但是它看起来可以选择其中一个 - 但不能同时选择两个! 我可以很好地画出我的TkInter窗口,但是如果我调用该函数开始监听RFID输入,然后该位运行正常并且可以正常工作...则不需要GUI。

代码如下。 你可以看到我的调试工作到目前为止,我的打印输出到终端...

    #!/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 / TkInter n00b,它已经被我殴打,我都完成了谷歌搜索。 任何帮助感激地收到:)


Tkinter(以及所有的GUI)都有一个叫做mainloop的无限循环,使GUI保持活跃和响应。 当你进行另一次无限循环( while True )时,你会阻止Tkinter的主循环; 并且GUI失败。 您需要将您的循环放在单独的线程中,或者使用Tkinter的主循环来完成您的工作。 由于您正在使用阻塞readline ,因此该线程是最佳途径。 作为一个猜测,用这个替换你的电话:

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导入应该看起来的样子:

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

然后你使用适当的前缀:

self.tk = tk.Tk()
self.frame = tk.Frame(self.tk)

你应该使用after来运行listen_rfid 。 问题是listen_rfid如你所写,它将永远运行,这意味着mainloop永远不会启动。 如果你这样做:

#!/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()

它会每半秒检查命令行是否有输入并处理它。

链接地址: http://www.djcxy.com/p/65023.html

上一篇: TkInter Frame doesn't load if another function is called

下一篇: ImportError: No module named PyQt4 on my Raspberry Pi