Home > Enterprise >  How to start a thread to update network data in tkinter when window opens without using a button
How to start a thread to update network data in tkinter when window opens without using a button

Time:01-28

The following code updates a label with the price of BTCUSDT downloaded from the Binance public API. The thread is started with a button, but I can't work out how to start it without the button, when the window opens.

from tkinter import *
import time
import requests      
import threading

def get_price():
    while True:
        root_url = 'https://api.binance.com/api/v3/avgPrice'
        symbol = 'BTCUSDT'
        url = root_url   '?symbol='   symbol
        data = requests.get(url).json()
        my_label.config(text=data['price'])
        time.sleep(60)
        

root = Tk()
root.geometry('400x200')

my_label = Label(root, text='Hello There')
my_label.pack(pady=20)

my_button = Button(root, text='Start', command=lambda:threading.Thread(target=get_price).start())
my_button.pack(pady=20)

root.mainloop()

CodePudding user response:

I would suggest to decouple the main thread with the one that performs the

reading of the data using the library queue,thing that you can easily do with

an Object Oriented approach.

I've put time to 3 seconds, regards.

#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import threading
import queue
import time
import requests  


class MyTrhead(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

        self.queue = queue.Queue()
        self.check = True

    def stop(self):
        self.check = False

    def run(self):

        """Feeds the tail."""

        while self.check:
            root_url = 'https://api.binance.com/api/v3/avgPrice'
            symbol = 'BTCUSDT'
            url = root_url   '?symbol='   symbol
            data = requests.get(url).json()
            msg = data['price']
            print("on run: {0}".format(msg))
            time.sleep(3)
            self.queue.put(msg)
    
    def check_queue(self, obj):

        """Returns a formatted string"""

        while self.queue.qsize():
            try:
                x = self.queue.get(0)
                msg = "{0}".format(x)
                print("check_queue {0}".format(msg))
                obj.set(msg)
            except queue.Empty:
                pass
            

class App(tk.Tk):
    """Application start here"""
    def __init__(self):
        super().__init__()

        self.title("Simple App")

        self.protocol("WM_DELETE_WINDOW", self.on_close)

        self.data = tk.StringVar()

        self.data.set("Hello World")

        self.init_ui()

        self.on_start()
       
    def init_ui(self):

        f0 = ttk.Frame(self)

        self.my_label = ttk.Label(f0, textvariable=self.data)
        self.my_label.pack()
        
        f0.pack(fill=tk.BOTH, expand=1)

    def on_start(self):

          self.my_thread = MyTrhead()
          self.my_thread.start()
          self.periodic_call()        
        
    def periodic_call(self):

        self.my_thread.check_queue(self.data)

        if self.my_thread.is_alive():
            self.after(1, self.periodic_call)
        else:
            pass
                
    def on_close(self, evt=None):

        msg = "Do you want to quit?"
        if messagebox.askokcancel(self.title(), msg, parent=self):
            if self.my_thread is not None:
                self.my_thread.stop()

            self.destroy()

def main():
    app = App()
    app.mainloop()

if __name__ == '__main__':
    main()            
    

enter image description here

enter image description here

  •  Tags:  
  • Related