如果调用另一个函数,则不加载TkInter Frame

问题描述 投票:4回答:2

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

这个拼图的两个部分都是孤立的,但是就目前而言,我似乎能够选择其中一个 - 但不是两个都可以!我可以很好地绘制我的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它打败了我,我已经完成了谷歌搜索。任何帮助感激地收到:)

python python-2.7 python-3.x user-interface tkinter
2个回答
3
投票

Tkinter(和所有GUI)都有一个称为mainloop的无限循环,可以保持GUI的活动和响应。当你进行另一个无限循环(while True)时,你阻止了Tkinter的主循环;并且GUI失败。你需要将循环放在一个单独的线程中,或者使用Tkinter的mainloop来完成你的工作。由于你使用阻塞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()

编辑:BTW,你的进口非常糟糕。 “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)

2
投票

你应该使用listen_rfid运行after。问题是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()

它将每半秒检查命令行上是否有一些输入并处理它。

© www.soinside.com 2019 - 2024. All rights reserved.