tkinter调用API时对话框冻结不显示,如何实现加载弹窗并移除窗口控制按钮
问题1:API调用时界面冻结、加载对话框无法弹出
原因
Tkinter 是单线程模型,所有界面渲染、用户交互事件都在主事件循环中顺序执行。你代码中的requests.post是同步阻塞操作,执行时会卡住主事件循环,导致加载对话框的渲染逻辑迟迟得不到执行,直到请求完成后才会执行后续的销毁逻辑,自然看不到加载框。
解决方案
用子线程执行API请求逻辑,所有界面更新操作(包括加载框销毁、页面跳转)通过after方法调度回主线程执行,修改后代码如下:
import threading import tkinter as tk from tkinter import ttk import json import requests import pickle def login_button_fuction(): # 先渲染加载框 top = tk.Toplevel(self) top.title("loading") top.geometry("200x100") top.resizable(0, 0) bar = ttk.Progressbar(top, orient="horizontal", length=100, mode="indeterminate") bar.pack(pady=25) bar.start() # 把请求逻辑放到子线程执行 def do_request(): url = "XXXXXXXXXXXXXXXXXXX" payload = json.dumps( {"username": username_entry.get(), "password": password_entry.get()}) headers = {'Content-Type': 'application/json'} response = requests.post(url+"/users/getuser", data=payload, headers=headers) result = response.json() # 请求完成后,调度主线程执行后续界面操作 def update_ui(): if result["resultCode"] == 100: print("success") data = { "realname": result["data"]["realname"], "phone": result["data"]["phone"]} with open("user_data.dat", "wb") as f: pickle.dump(data, f) controller.show_frame(dashboardPage.dashboard_page) else: print("error") bar.stop() top.destroy() # 10ms后主线程执行UI更新 self.after(10, update_ui) threading.Thread(target=do_request, daemon=True).start()
问题2:移除对话框的最小化和关闭按钮
有两种常用方案,可按需选择:
- 仅移除最小化按钮、保留标题栏,可同时禁用关闭按钮:
# 设置为工具窗口样式,自动去掉最小化按钮 top.attributes('-toolwindow', True) # 可选:禁用关闭按钮,点击关闭无响应 top.protocol("WM_DELETE_WINDOW", lambda: None)
- 完全移除整个标题栏(包括最小化、关闭、标题,无任何窗口控制按钮):
top.overrideredirect(True)
注意使用overrideredirect后窗口无法拖动,需要自定义拖动逻辑,常规加载提示场景用第一种工具窗口的方案即可。
内容的提问来源于stack exchange,提问作者lexi
相关产品推荐
相关产品推荐

