在 Windows 中使用 tkinter 调用 mainloop 时保持控制台焦点
Keep console focus when calling mainloop with tkinter in Windows
我正在使用 cmd.exe 到 运行 打开 tkinter window 的程序。当调用 root.mainloop() 函数时,我想将注意力集中在控制台上。下面的示例代码。这是 运行ning 在 Window 系统上 Python 3.9.
# gui thread
def guiTask():
print("doing tasks here")
root.after(50, guiTask)
# main GUI
root = tk.Tk()
root.geometry('%dx%d' % (800, 800))
root.after(50, guiTask)
root.mainloop()
因此这段代码将在打开 tkinter window 后每 50 毫秒打印一些内容。执行时焦点转到 window。我希望焦点保持在控制台上。这可能吗?
Windows 仅(据我所知):
好吧,我找到了一种方法(部分地(指的是大部分功能)取自 Get HWND of each Window?(问题本身)):
import tkinter as tk
def win_focus_set(win_name):
import ctypes
enum_windows = ctypes.windll.user32.EnumWindows
enum_windows_proc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
get_window_text = ctypes.windll.user32.GetWindowTextW
get_window_text_length = ctypes.windll.user32.GetWindowTextLengthW
is_window_visible = ctypes.windll.user32.IsWindowVisible
windows = []
def foreach_window(hwnd, _):
if is_window_visible(hwnd):
length = get_window_text_length(hwnd)
buff = ctypes.create_unicode_buffer(length + 1)
get_window_text(hwnd, buff, length + 1)
windows.append((hwnd, buff.value))
return True
enum_windows(enum_windows_proc(foreach_window), 0)
for hwnd, name in windows:
if win_name in name:
ctypes.windll.user32.BringWindowToTop(hwnd)
def gui_task():
print("doing tasks here")
root.after(50, gui_task)
# main GUI
root = tk.Tk()
root.geometry('%dx%d' % (800, 800))
root.after(50, gui_task)
root.after(1, win_focus_set, 'cmd.exe')
root.mainloop()
基本上就是那个函数,然后使用 .after
尽快调用它,以便它在主 window 出现后立即执行(还有 "cmd.exe"
在 window 的标题中(因此,如果您打开了两个 cmd,它可能会切换到另一个(尽管如果它们具有相同的标题,即使您提供了完整的标题,也会发生这种情况))和 .after
将其余参数作为传递给预定函数的参数)
另一种选择是获取当前处于焦点的 window 并在 tkinter
开始后将其置于顶部:
import tkinter as tk
import ctypes
hwnd = ctypes.windll.user32.GetForegroundWindow()
def gui_task():
print("doing tasks here")
root.after(50, gui_task)
# main GUI
root = tk.Tk()
root.geometry('%dx%d' % (800, 800))
root.after(50, gui_task)
root.after(1, ctypes.windll.user32.BringWindowToTop, hwnd)
root.mainloop()
我正在使用 cmd.exe 到 运行 打开 tkinter window 的程序。当调用 root.mainloop() 函数时,我想将注意力集中在控制台上。下面的示例代码。这是 运行ning 在 Window 系统上 Python 3.9.
# gui thread
def guiTask():
print("doing tasks here")
root.after(50, guiTask)
# main GUI
root = tk.Tk()
root.geometry('%dx%d' % (800, 800))
root.after(50, guiTask)
root.mainloop()
因此这段代码将在打开 tkinter window 后每 50 毫秒打印一些内容。执行时焦点转到 window。我希望焦点保持在控制台上。这可能吗?
Windows 仅(据我所知):
好吧,我找到了一种方法(部分地(指的是大部分功能)取自 Get HWND of each Window?(问题本身)):
import tkinter as tk
def win_focus_set(win_name):
import ctypes
enum_windows = ctypes.windll.user32.EnumWindows
enum_windows_proc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
get_window_text = ctypes.windll.user32.GetWindowTextW
get_window_text_length = ctypes.windll.user32.GetWindowTextLengthW
is_window_visible = ctypes.windll.user32.IsWindowVisible
windows = []
def foreach_window(hwnd, _):
if is_window_visible(hwnd):
length = get_window_text_length(hwnd)
buff = ctypes.create_unicode_buffer(length + 1)
get_window_text(hwnd, buff, length + 1)
windows.append((hwnd, buff.value))
return True
enum_windows(enum_windows_proc(foreach_window), 0)
for hwnd, name in windows:
if win_name in name:
ctypes.windll.user32.BringWindowToTop(hwnd)
def gui_task():
print("doing tasks here")
root.after(50, gui_task)
# main GUI
root = tk.Tk()
root.geometry('%dx%d' % (800, 800))
root.after(50, gui_task)
root.after(1, win_focus_set, 'cmd.exe')
root.mainloop()
基本上就是那个函数,然后使用 .after
尽快调用它,以便它在主 window 出现后立即执行(还有 "cmd.exe"
在 window 的标题中(因此,如果您打开了两个 cmd,它可能会切换到另一个(尽管如果它们具有相同的标题,即使您提供了完整的标题,也会发生这种情况))和 .after
将其余参数作为传递给预定函数的参数)
另一种选择是获取当前处于焦点的 window 并在 tkinter
开始后将其置于顶部:
import tkinter as tk
import ctypes
hwnd = ctypes.windll.user32.GetForegroundWindow()
def gui_task():
print("doing tasks here")
root.after(50, gui_task)
# main GUI
root = tk.Tk()
root.geometry('%dx%d' % (800, 800))
root.after(50, gui_task)
root.after(1, ctypes.windll.user32.BringWindowToTop, hwnd)
root.mainloop()