跳到正文
DEV Community· Yunus Emre Güzel·· 3 小時前AI 評分51

Tkinter 應用程式為何會凍結,以及如何修復

Why Your Tkinter App Freezes (Not Responding) and How to Fix It

AI 導讀

Tkinter 應用程式在慢速工作佔用主執行緒時會凍結;文章示範把工作放到背景執行緒,再用 window.after() 將結果交回主執行緒。作者提醒,只有主執行緒可以操作 Tkinter 元件,從背景執行緒直接修改元件可能引發錯誤或當機。

正文

You build a Tkinter app that fetches the weather, asks an AI model a question, or downloads a file. You click the button and the whole window freezes. You can’t drag it, the button stays pressed, and Windows adds “(Not Responding)” to the title. A few seconds later it suddenly comes back with the answer. It shows up in exactly the kind of apps from my Tkinter guide, like the weather app and the AI image app, and the fix is the same every time.

The Problem: The Window Freezes While It Works

Here is a small app that shows the problem. time.sleep(3) stands in for any slow job, like an API call:

import time
import tkinter as tk

def on_click():
    label.config(text="Loading...")
    time.sleep(3)  # pretend this is an API call
    label.config(text="Done!")

window = tk.Tk()
label = tk.Label(window, text="Click the button", font=("Arial", 14))
label.pack(padx=20, pady=10)
tk.Button(window, text="Start", command=on_click).pack(pady=10)
window.mainloop()

Click Start and the window locks up for three seconds. You never even see “Loading…”.

Why Tkinter Freezes

Everything in a Tkinter app runs on one main thread. window.mainloop() is a loop that keeps redrawing the window and handling clicks. When you click the button, mainloop() calls your function and waits for it to finish.

While your function sits in time.sleep() or waits for a server, mainloop() can’t do anything else. No redraws, no clicks, no “Loading…” text. That’s also why the label change never shows: Tkinter only redraws once your function returns.

The Fix: Run Slow Work in a Thread

Move the slow part into a background thread, so the main thread is free to keep the window alive. When the work is done, hand the result back to the main thread with window.after():

import threading
import time
import tkinter as tk

def slow_task():
    time.sleep(3)  # the API call goes here
    window.after(0, show_result, "Done!")  # back to the main thread

def show_result(text):
    label.config(text=text)
    button.config(state="normal")

def on_click():
    button.config(state="disabled")
    label.config(text="Loading...")
    threading.Thread(target=slow_task, daemon=True).start()

window = tk.Tk()
label = tk.Label(window, text="Click the button", font=("Arial", 14))
label.pack(padx=20, pady=10)
button = tk.Button(window, text="Start", command=on_click)
button.pack(pady=10)
window.mainloop()

Now “Loading…” appears straight away, and you can drag the window around while the task runs.

What each part does

  • threading.Thread(target=slow_task, daemon=True).start() runs slow_task at the same time as the window. daemon=True means the thread won’t keep Python running after you close the window.

  • window.after(0, show_result, "Done!") asks the main thread to run show_result("Done!") as soon as it can.

  • Disabling the button stops people from clicking Start ten times and starting ten threads.

The One Rule: Only the Main Thread Touches Widgets

It’s tempting to write label.config(text="Done!") directly inside slow_task. Sometimes that even seems to work. But Tkinter isn’t thread-safe, so changing widgets from another thread can cause random errors and crashes that are very hard to track down. Always go through window.after().

The same pattern works for any slow job: requests.get() for an API, a call to an AI model, reading a big file, or processing an image with Pillow.

Where to Go Next

My Tkinter in Python guide goes from a first window to full projects, including the weather and AI apps where this fix matters most. If you’re still getting used to Python itself, start with Python for beginners.

Did your Tkinter app freeze on something else? Paste the error in the comments, and I’ll take a look.


Originally published on my blog. I post new C, Python and AI-agent guides there regularly.

來源:DEV Community · dev.to