Tkinter自定义弹窗如何实现打开时禁用主窗口、关闭后恢复功能
问题修复方案
你要实现的是Tkinter的模态弹窗效果,只要修改两处核心逻辑即可实现需求:
- 自定义弹窗不要用
Tk()创建,改用Tkinter专门给子窗口提供的Toplevel()类,避免多主窗口导致的事件逻辑混乱 - 给弹窗调用
grab_set()方法,即可拦截所有输入事件到弹窗上,此时主窗口所有操作都会被屏蔽,弹窗销毁后自动恢复主窗口操作权限
修复后完整可运行代码
from tkinter import * win = Tk() win.title("Main Window") # 原代码缺少save_func实现,这里补充占位逻辑,你可以替换成自己的保存功能 def save_func(): print("文件已保存") def closing_try(): # 把Tk()改成Toplevel()创建子窗口 close = Toplevel(win) close.title("Warning") close.geometry('200x100') close.overrideredirect(0) close.configure(bg='white') close.resizable(False, False) close.attributes("-topmost", True) close.eval('tk::PlaceWindow . center') # 加上grab_set实现模态效果,拦截所有事件到当前弹窗 close.grab_set() def save_b_func(): close.destroy() save_func() win.destroy() def dont_save_b_func(): win.destroy() close.destroy() def cancel_b_func(): close.destroy() ask_lbl = Label(close, text='''Do You Want to Save File Before Exiting?''', bg='white', font=('consolas', 10, 'normal')) ask_lbl.place(x=10, y=5) save_b = Button(close, text='Save', font=('consolas', 10, 'normal'), command=save_b_func, bg='white').place(x=9, y=50) dont_save_b = Button(close, text="Don't Save", font=('consolas', 10, 'normal'), command=dont_save_b_func, bg='white').place(x=53, y=50) cancel_b = Button(close, text='Cancel', font=('consolas', 10, 'normal'), command=cancel_b_func, bg='white').place(x=139, y=50) # 删掉多余的close.mainloop(),子窗口不需要单独启动事件循环,主窗口的mainloop会统一处理 button = Button(win, text='click me', command = closing_try).pack() win.mainloop()
额外说明
- 不用再手动写禁用主窗口、恢复主窗口的逻辑,
grab_set()已经自动处理了所有事件拦截的逻辑 - 删掉了子窗口单独的
mainloop(),同一个Tkinter程序只需要一个主事件循环即可,多写会导致逻辑异常 - 如果要支持用户点击弹窗右上角关闭按钮也能正常释放权限,你可以给弹窗绑定
WM_DELETE_WINDOW事件,指向取消操作的逻辑即可。
内容的提问来源于stack exchange,提问作者Mentally Strong
相关产品推荐
相关产品推荐

