Windows下调用tkinter的mainloop时如何保持控制台焦点
Windows下Tkinter启动时保持控制台焦点的解决方案
实现原理
Windows系统下Tkinter窗口初始化完成后会自动抢占系统前台焦点,我们可以通过调用Win32 API实现两种不同效果的焦点保持方案,两种方案均依赖Python内置的ctypes库,无需安装第三方依赖。
方案1:启动后自动切回控制台焦点
该方案仅在程序启动时将焦点切回控制台,后续仍可正常点击激活Tkinter窗口,适合需要偶尔操作GUI的场景:
import tkinter as tk import ctypes from ctypes import wintypes # 加载Win32 API user32 = ctypes.WinDLL('user32', use_last_error=True) user32.GetForegroundWindow.argtypes = () user32.GetForegroundWindow.restype = wintypes.HWND user32.SetForegroundWindow.argtypes = (wintypes.HWND,) user32.SetForegroundWindow.restype = wintypes.BOOL # 提前保存当前控制台的窗口句柄(此时焦点还在控制台) console_hwnd = user32.GetForegroundWindow() def guiTask(): print("doing tasks here") root.after(50, guiTask) # 初始化GUI root = tk.Tk() root.geometry('%dx%d' % (800, 800)) # 等待GUI完成渲染 root.update() # 将焦点切回控制台 user32.SetForegroundWindow(console_hwnd) root.after(50, guiTask) root.mainloop()
方案2:禁止Tkinter窗口自动抢占焦点
该方案会给Tkinter窗口添加WS_EX_NOACTIVATE扩展样式,全程不会自动抢焦点,只有用户手动点击窗口才会激活,适合仅需要查看GUI输出、不需要频繁操作的场景:
import tkinter as tk import ctypes from ctypes import wintypes # 定义Win32常量 GWL_EXSTYLE = -20 WS_EX_NOACTIVATE = 0x08000000 # 加载Win32 API user32 = ctypes.WinDLL('user32', use_last_error=True) user32.GetWindowLongPtrW.argtypes = (wintypes.HWND, ctypes.c_int) user32.GetWindowLongPtrW.restype = wintypes.LONG_PTR user32.SetWindowLongPtrW.argtypes = (wintypes.HWND, ctypes.c_int, wintypes.LONG_PTR) user32.SetWindowLongPtrW.restype = wintypes.LONG_PTR def guiTask(): print("doing tasks here") root.after(50, guiTask) # 初始化GUI root = tk.Tk() root.geometry('%dx%d' % (800, 800)) # 获取Tkinter窗口的原生句柄 hwnd = ctypes.wintypes.HWND(int(root.frame(), 16)) # 给窗口添加不自动激活的扩展样式 ex_style = user32.GetWindowLongPtrW(hwnd, GWL_EXSTYLE) ex_style |= WS_EX_NOACTIVATE user32.SetWindowLongPtrW(hwnd, GWL_EXSTYLE, ex_style) root.after(50, guiTask) root.mainloop()
注意事项
两种方案均为Windows系统专属,依赖Win32 API实现,不适用于macOS、Linux等其他操作系统。
内容的提问来源于stack exchange,提问作者jliu83
相关产品推荐
相关产品推荐

