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

Python/Tkinter:如何防止主窗口失焦时退出全屏状态?

Tkinter全屏主窗口弹出子窗口/MessageBox时退出全屏的解决办法

我用Python/Tkinter开发了一款全屏应用,主窗口设置为全屏模式,但调用Toplevel窗口或MessageBox时,主窗口会退出全屏,系统任务栏随之显示。点击主窗口可重新聚焦并恢复全屏,请问有没有办法防止主窗口失焦时退出全屏?

复现代码

# coding: utf-8
from tkinter import *
from tkinter.messagebox import askokcancel, showinfo, WARNING

# 创建主窗口
fenetre = Tk()
larg = fenetre.winfo_screenwidth()
haut = fenetre.winfo_screenheight()
fenetre.title("Tests")
fenetre.geometry(f"{larg}x{haut}+0+0")
fenetre.attributes("-fullscreen", 1)

def fermeture():
    reponse = askokcancel(title='Confirmation', message='Quitter ?', icon=WARNING)
    if reponse == True:
        fenetre.destroy()

bouton_quitter = Button(fenetre, text="quitter", command=fermeture)
bouton_quitter.place(x=larg/2, y=haut/2)
fenetre.mainloop()

我试过用fenetre.after(500, ffocus)强制主窗口在MessageBox弹出后重新聚焦,但效果不好:一是仍会短暂失焦显示任务栏;二是500ms的延迟会因处理器性能差异出现适配问题。另外也尝试给MessageBox添加parent=fenetre参数,但是没有改善。


解决方案

方法1:绑定焦点事件自动恢复全屏

给主窗口绑定<<FocusIn>>事件,一旦主窗口重新获得焦点就立刻重置全屏属性,能最大程度减少任务栏显示的时间,体验比延迟聚焦好很多:

# coding: utf-8
from tkinter import *
from tkinter.messagebox import askokcancel, WARNING

def restore_fullscreen(event):
    fenetre.attributes("-fullscreen", 1)

fenetre = Tk()
larg = fenetre.winfo_screenwidth()
haut = fenetre.winfo_screenheight()
fenetre.title("Tests")
fenetre.attributes("-fullscreen", 1)

# 绑定焦点进入事件,自动恢复全屏
fenetre.bind("<<FocusIn>>", restore_fullscreen)

def fermeture():
    # 务必指定parent参数,让MessageBox归属于主窗口
    reponse = askokcancel(title='Confirmation', message='Quitter ?', icon=WARNING, parent=fenetre)
    if reponse == True:
        fenetre.destroy()

bouton_quitter = Button(fenetre, text="quitter", command=fermeture)
bouton_quitter.place(x=larg/2, y=haut/2)
fenetre.mainloop()

方法2:用overrideredirect替代原生全屏

如果任务栏弹出的问题特别顽固,可以尝试隐藏窗口的系统装饰,手动设置窗口为屏幕尺寸。注意这个方法会让窗口失去系统默认的拖动、关闭等功能,需要自己实现:

# coding: utf-8
from tkinter import *
from tkinter.messagebox import askokcancel, WARNING

fenetre = Tk()
larg = fenetre.winfo_screenwidth()
haut = fenetre.winfo_screenheight()
fenetre.title("Tests")

# 隐藏窗口边框和标题栏,手动设置全屏尺寸
fenetre.overrideredirect(True)
fenetre.geometry(f"{larg}x{haut}+0+0")

def fermeture():
    reponse = askokcancel(title='Confirmation', message='Quitter ?', icon=WARNING, parent=fenetre)
    if reponse == True:
        fenetre.destroy()

# 自定义关闭按钮
bouton_quitter = Button(fenetre, text="quitter", command=fermeture)
bouton_quitter.place(x=larg/2, y=haut/2)

# 可以添加ESC快捷键退出
fenetre.bind("<Escape>", lambda e: fenetre.destroy())

fenetre.mainloop()

方法3:Windows系统专属优化

如果是在Windows平台运行,可以调用系统API把主窗口设为最顶层,进一步减少任务栏弹出的概率:

# coding: utf-8
import ctypes
from tkinter import *
from tkinter.messagebox import askokcancel, WARNING

# Windows API设置窗口为最顶层
HWND_TOPMOST = -1
SWP_NOMOVE = 0x0002
SWP_NOSIZE = 0x0001

def set_topmost(window):
    hwnd = ctypes.windll.user32.GetParent(window.winfo_id())
    ctypes.windll.user32.SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE)

fenetre = Tk()
larg = fenetre.winfo_screenwidth()
haut = fenetre.winfo_screenheight()
fenetre.title("Tests")
fenetre.attributes("-fullscreen", 1)

# 把主窗口设为最顶层
set_topmost(fenetre)

def fermeture():
    reponse = askokcancel(title='Confirmation', message='Quitter ?', icon=WARNING, parent=fenetre)
    if reponse == True:
        fenetre.destroy()

bouton_quitter = Button(fenetre, text="quitter", command=fermeture)
bouton_quitter.place(x=larg/2, y=haut/2)
fenetre.mainloop()

内容的提问来源于stack exchange,提问作者Jouski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 16:39:21