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

如何在Python的Tkinter中点击窗口时保持其不获取焦点?

问题

我正在开发一款带希腊字母面板的应用,点击面板按钮就能把字符输入到当前使用的文本框里。但点击按钮时,Tk窗口会抢走焦点,导致字符没法粘贴到之前的窗口。试过给Button加takefocus=0,但这只对键盘导航有用,想知道怎么让窗口不获取焦点。

当前代码:

from tkinter import *
import math
import pyautogui


class App(Tk):
    def __init__(self):
        super().__init__()
        self.rows = 4
        self.alphabet = ["Αα", "Ββ", "Γγ", "Δδ", "Εε", "Ζζ", "Ηη", "Θθ", "Ιι", "Κκ", "Λλ", "Μμ", "Νν", "Ξξ", "Οο", "Ππ",
                         "Ρρ", "Σσ", "Ττ", "Υυ", "Φφ", "Χχ", "Ψψ", "Ωω"]
        self.buttons = [Button(text=i[1],
                               command=(lambda: self.paste(i)),
                               font=('Times New Roman', 16, 'bold'),
                               takefocus=0) for i in self.alphabet]

        blen = math.ceil(len(self.buttons) / self.rows)
        for i in range(0, self.rows):
            self.grid_rowconfigure(i, weight=1)
            for j in range(0, blen):
                self.grid_columnconfigure(j, weight=1)
                if i * blen + j < len(self.buttons):
                    self.buttons[i * blen + j].grid(row=i, column=j, ipadx=4, ipady=4, sticky="nesw")

    def paste(self, string): # probably need to do this differently
        self.clipboard_clear()
        self.clipboard_append(string[1])
        pyautogui.hotkey("ctrl", "v")


if __name__ == "__main__":
    app = App()
    app.attributes('-topmost', True)
    app.mainloop()
解决方案

Tk本身没有直接提供让窗口不获取焦点的属性,需要借助Win32 API修改窗口样式,同时优化字符输入逻辑:

修改步骤

  1. 引入ctypes库调用Win32 API,给窗口添加WS_EX_NOACTIVATE扩展样式,这个样式能让窗口不会因鼠标点击获取焦点。
  2. 修正lambda变量捕获问题,避免所有按钮触发最后一个字符的输入。
  3. 替换剪贴板粘贴为直接输入,用pyautogui.typewrite直接输出字符,省去剪贴板操作,避免覆盖原有剪贴板内容。

修改后的完整代码

from tkinter import *
import math
import pyautogui
import ctypes
from ctypes import wintypes

# Win32 API常量与函数定义
GWL_EXSTYLE = -20
WS_EX_NOACTIVATE = 0x08000000

user32 = ctypes.WinDLL('user32', use_last_error=True)
user32.GetWindowLongPtrW.restype = wintypes.LONG_PTR
user32.GetWindowLongPtrW.argtypes = (wintypes.HWND, wintypes.INT)
user32.SetWindowLongPtrW.restype = wintypes.LONG_PTR
user32.SetWindowLongPtrW.argtypes = (wintypes.HWND, wintypes.INT, wintypes.LONG_PTR)


class App(Tk):
    def __init__(self):
        super().__init__()
        self.rows = 4
        self.alphabet = ["Αα", "Ββ", "Γγ", "Δδ", "Εε", "Ζζ", "Ηη", "Θθ", "Ιι", "Κκ", "Λλ", "Μμ", "Νν", "Ξξ", "Οο", "Ππ",
                         "Ρρ", "Σσ", "Ττ", "Υυ", "Φφ", "Χχ", "Ψψ", "Ωω"]
        # 修正lambda变量捕获问题,确保每个按钮绑定对应字符
        self.buttons = [Button(text=i[1],
                               command=(lambda char=i: self.paste(char)),
                               font=('Times New Roman', 16, 'bold'),
                               takefocus=0) for i in self.alphabet]

        blen = math.ceil(len(self.buttons) / self.rows)
        for i in range(0, self.rows):
            self.grid_rowconfigure(i, weight=1)
            for j in range(0, blen):
                self.grid_columnconfigure(j, weight=1)
                if i * blen + j < len(self.buttons):
                    self.buttons[i * blen + j].grid(row=i, column=j, ipadx=4, ipady=4, sticky="nesw")

        # 保持窗口始终置顶
        self.attributes('-topmost', True)
        # 窗口初始化完成后设置无焦点样式
        self.after(100, self.set_no_activate)

    def set_no_activate(self):
        # 获取Tk窗口的系统句柄
        hwnd = wintypes.HWND(self.winfo_id())
        # 获取当前窗口扩展样式
        ex_style = user32.GetWindowLongPtrW(hwnd, GWL_EXSTYLE)
        # 添加WS_EX_NOACTIVATE样式,阻止窗口获取焦点
        user32.SetWindowLongPtrW(hwnd, GWL_EXSTYLE, ex_style | WS_EX_NOACTIVATE)
        # 更新窗口样式
        user32.SetWindowPos(hwnd, None, 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0040)

    def paste(self, char):
        # 直接输入目标字符,无需依赖剪贴板
        pyautogui.typewrite(char[1])


if __name__ == "__main__":
    app = App()
    app.mainloop()

关键说明

  • WS_EX_NOACTIVATE样式是Windows系统特有的,能让窗口成为"非激活"窗口,鼠标点击不会让它获取焦点,完全不影响之前操作的窗口。
  • after(100, ...)是为了等窗口完全初始化后再修改样式,避免因句柄未就绪导致操作失败。
  • 修正lambda变量捕获是因为原代码中lambda会引用循环变量的最终值,导致所有按钮都触发最后一个字符的输入,改用char=i可以捕获当前循环的变量值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:49:54