window 在不使用按钮的情况下打开时如何启动线程以更新 tkinter 中的网络数据
How to start a thread to update network data in tkinter when window opens without using a button
以下代码使用从 Binance public API 下载的 BTCUSDT 价格更新标签。该线程是通过一个按钮启动的,但是当 window 打开时,我不知道如何在没有按钮的情况下启动它。
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()
我建议将主线程与执行
的线程分离
使用库队列读取数据,你可以轻松完成的事情
面向对象的方法。
我把时间调到了 3 秒,问候。
#!/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()
以下代码使用从 Binance public API 下载的 BTCUSDT 价格更新标签。该线程是通过一个按钮启动的,但是当 window 打开时,我不知道如何在没有按钮的情况下启动它。
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()
我建议将主线程与执行
的线程分离使用库队列读取数据,你可以轻松完成的事情
面向对象的方法。
我把时间调到了 3 秒,问候。
#!/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()