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

时间:2017-06-20 16:22:37

标签: python python-2.7 python-3.x user-interface 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它击败了我并且我完成了谷歌搜索。感谢任何帮助:)

2 个答案:

答案 0 :(得分:3)

Tkinter(以及所有GUI)都有一个名为mainloop的无限循环,可以保持GUI的活动和响应。当你进行另一个无限循环(// first approach angular.controller("MyController", function() { $scope.firstFun = function() { // do something here }; }); // second approach var firstFun = function($scope) { return function() { //use scope here and declare logic also }; }; angular.controller("MyController", function() { $scope.firstFun = firstFun($scope); }); )时,你阻止了Tkinter的主循环;并且GUI失败。你需要将循环放在一个单独的线程中,或者使用Tkinter的主循环来完成你的工作。由于您使用了阻塞while True,因此该线程是最好的方法。猜测一下,用这个替换你的电话:

readline
编辑:BTW,你的进口非常糟糕。 &#34; TTK&#34;是tkinter的子集,而不是别名,别名&#34; tk&#34;通常用于tkinter,通配符导入很糟糕,应该避免。这就是你的tkinter导入的样子:

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()

然后使用适当的前缀:

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

答案 1 :(得分: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()

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