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

Tkinter从网络拉取数据时加载动画/进度条不生效如何解决

问题根源

Tkinter 为单线程事件驱动模型,你当前将网络请求这类阻塞IO操作和UI控制逻辑都放在主线程的get()方法中执行,网络请求过程会直接卡住Tkinter的主事件循环,进度条的刷新渲染逻辑无法得到调度,直到所有数据拉取完成后才会一次性更新UI,因此看不到加载动画的运行效果。

修复方案

将耗时的网络请求逻辑拆分到独立子线程运行,避免阻塞主线程的UI渲染,网络请求完成后通过Tkinter原生的after()方法通知主线程执行进度条停止、海报渲染的UI操作(Tkinter所有UI相关操作都不允许在子线程直接调用)。

修改后完整代码

from tkinter import *
from tkinter import ttk
import io
import threading
from PIL import Image, ImageTk
import requests
from urllib.request import urlopen


class Root(Tk):
    def __init__(self):
        super().__init__()
        # 窗口初始化
        self.geometry("720x1000")
        self.canvas = Canvas(width=720, height=1000)
        self.canvas.place(relx=0, rely=0)
        
        self.button = Button(self, text="Get The Posters", command=self.get)
        self.button.pack()
        
        self.movie_list = ["Tenet", "Memento", "Inception"]
        self.poster_list = []
        self.x = 0
        
    def fetch_posters(self):
        # 子线程执行耗时的网络请求逻辑
        for i in self.movie_list:
            url = "http://www.omdbapi.com/?apikey=73a4d84d&t={}".format(i)
            response = requests.get(url)
            data = response.json()
            pic_url = data["Poster"]
            my_page = urlopen(pic_url)
            my_picture = io.BytesIO(my_page.read())
            pil_img = Image.open(my_picture).resize((200,296))
            tk_img = ImageTk.PhotoImage(pil_img)
            self.poster_list.append(tk_img)
        # 请求完成后通知主线程更新UI
        self.after(0, self.show_posters)
        
    def show_posters(self):
        # 主线程执行UI更新逻辑
        self.pb.stop()
        self.label.destroy()
        self.pb.destroy()
        # 渲染海报
        x = 0
        for n in range(len(self.poster_list)):
            x += 30
            if n == 1 or n == 2:
                x += 200
            self.canvas.create_image(x, 100, image=self.poster_list[n], anchor=NW)

    def get(self):
        # 主线程处理UI初始化
        self.button.destroy()
        self.label = Label(text="loading")
        self.label.place(relx=0.08, rely=0.65)
        self.pb = ttk.Progressbar(orient='horizontal', mode='indeterminate', length=480)
        self.pb.place(relx=0.08, rely=0.7)
        self.pb.start()
        # 启动子线程拉取数据
        threading.Thread(target=self.fetch_posters, daemon=True).start()

root = Root()
root.mainloop()

内容的提问来源于stack exchange,提问作者newfile.py

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 14:45:03