You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter界面调用API获取ISS位置并在Canvas显示时卡顿的解决求助

Tkinter界面调用API获取ISS位置并在Canvas显示时卡顿的解决求助

嗨,我完全懂你遇到的困扰——运行一段时间后UI就卡得动不了,对吧?咱们来拆解问题,一步步把它修好。

问题出在哪?

你的代码里,requests.get()是同步阻塞式的网络请求。每次调用这个方法时,Tkinter的主事件循环(就是管UI更新、用户点击这些交互的核心)会被彻底卡住,直到API返回数据才会继续干活。哪怕你只设了1秒间隔,只要网络偶尔延迟、或者API响应慢,这些阻塞累积起来,UI就会越来越卡,最后直接假死。

而且Tkinter有个严格规则:所有UI操作必须在主线程里执行,直接把同步请求塞在循环里,肯定会出问题。

解决方案:用线程分离网络操作

咱们把网络请求的活儿丢给单独的子线程干,让主线程专心处理UI,这样就不会阻塞界面了。注意!绝对不能在子线程里直接改Tkinter的UI元素,必须让主线程来做这件事。

这里用Python自带的threading模块实现,配合Tkinter的after()方法来安全更新UI。

修改后的完整代码如下:

from tkinter import *
import requests
import threading

def fetch_iss_position():
    # 子线程只负责网络请求,不碰UI
    try:
        # 给请求加超时,避免网络出问题时一直卡着
        data = requests.get(url="http://api.open-notify.org/iss-now.json", timeout=5)
        data.raise_for_status()
        data = data.json()
        lat = data["iss_position"]["latitude"]
        long = data["iss_position"]["longitude"]
        # 让主线程来更新UI,这是线程安全的做法
        window.after(0, update_ui, lat, long)
    except Exception as e:
        print(f"请求出错啦: {e}")
    # 不管成功失败,1秒后再启动下一次请求线程
    window.after(1000, start_fetch_thread)

def update_ui(lat, long):
    # 这个函数在主线程执行,专门负责更新Canvas文本
    my_canvas.itemconfig(my_text, text=f"latitude = {lat}\nlongitude = {long}")

def start_fetch_thread():
    # 启动新的子线程处理请求
    thread = threading.Thread(target=fetch_iss_position)
    thread.daemon = True  # 设置守护线程,关闭窗口时线程自动退出,不残留后台进程
    thread.start()

window = Tk()
window.title("ISS Position")
window.config(padx=50, pady=50)
window.minsize(300, 300)
my_canvas = Canvas(height=300, width=300, highlightthickness=0)
my_canvas.grid(column=0, row=0, padx=10, columnspan=2)
my_text = my_canvas.create_text(150, 150, text="ISS POSITION", font=("arial", 16, "bold"))

my_button = Button(text="Enter", command=start_fetch_thread, font=("arial", 16, "bold"))
my_button.grid(column=0, row=1, columnspan=2)

window.mainloop()

关键改动说明

  • 把网络请求逻辑拆分到fetch_iss_position(),交给子线程执行,彻底解放主线程
  • 用window.after(0, update_ui, lat, long)通知主线程更新UI,这是Tkinter官方推荐的线程安全更新方式
  • 给requests.get()加了timeout=5,防止网络异常时请求无限挂起
  • 设置线程为守护线程,关闭窗口时自动结束,不会留下后台进程

额外小建议

  • ISS的位置其实没那么快的更新频率,1秒一次请求有点频繁,改成5秒一次既减轻API服务器压力,也能减少本地线程开销
  • 可以加个“停止”按钮,方便手动暂停追踪

这样修改后,你的UI应该就能一直流畅显示ISS的实时位置啦~

备注:内容来源于stack exchange,提问作者abhishek pandit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:02:57