对于Python gui,每几秒钟重复执行一个函数而不中断其他函数的最佳方法是什么?

时间:2019-03-24 00:45:07

标签: python user-interface tkinter timer

我想重复运行一个每60秒从API检索数据的函数。但是,我意识到我不能在不中断其他功能的情况下使其进入睡眠状态或使用while循环。

我的问题是,如何在不中断其他功能的情况下反复从API重复获取数据/重新运行首先获取数据的代码?

1 个答案:

答案 0 :(得分:0)

下面是一个完整的脚本,该脚本可从Open Notify检索ISS位置的经度和纬度并将其打印在线程上。

我已经设置了1秒时间。您可以启动和停止线程。现在尝试添加功能。

请注意,您必须导入此模​​块

  

导入请求

     

导入json

import tkinter as tk
import threading
import queue
import datetime
import time
import requests
import json

class MyThread(threading.Thread):

    def __init__(self, queue,):
        threading.Thread.__init__(self)

        self.queue = queue
        self.check = True


    def stop(self):
        self.check = False

    def run(self):

        while self.check:

            response = requests.get("http://api.open-notify.org/iss-now.json")
            data = response.json()
            time.sleep(1)
            self.queue.put(data)


class App(tk.Frame):

    def __init__(self,):

        super().__init__()

        self.master.title("Hello World")
        self.master.protocol("WM_DELETE_WINDOW",self.on_close)

        self.queue = queue.Queue()

        self.my_thread = None

        self.init_ui()

    def init_ui(self):

        self.f = tk.Frame()

        w = tk.Frame()

        tk.Button(w, text="Start", command=self.launch_thread).pack()
        tk.Button(w, text="Stop", command=self.stop_thread).pack()
        tk.Button(w, text="Close", command=self.on_close).pack()

        w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=0)
        self.f.pack(side=tk.LEFT, fill=tk.BOTH, expand=0)

    def launch_thread(self):

        if (threading.active_count()!=0):

            self.my_thread = MyThread(self.queue)
            self.my_thread.start()
            self.periodiccall()

    def stop_thread(self):
        if self.my_thread is not None:
            if(threading.active_count()!=1):
                self.my_thread.stop()


    def periodiccall(self):

        self.checkqueue()
        if self.my_thread.is_alive():
            self.after(1, self.periodiccall)
        else:
            pass

    def checkqueue(self):
        while self.queue.qsize():
            try:
                ret = self.queue.get(0)
                print("The ISS is currently over: {0} ".format(ret['iss_position']))
            except queue.Empty:
                pass                    

    def on_close(self):
        if self.my_thread is not None:
            if(threading.active_count()!=1):
                self.my_thread.stop()

        self.master.destroy()

if __name__ == '__main__':
    app = App()
    app.mainloop()