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

Tkinter循环创建ScrolledText焦点事件仅最后一个生效如何解决

问题解决思路与修复代码

问题本质

Python循环中的lambda表达式存在迟绑定特性:绑定回调时不会立即保存当前迭代的控件变量,事件触发时读取的变量已经是循环结束后最后一个控件的实例,因此所有事件都只对最后一个ScrolledText生效,和你设置的name属性没有关系。

最优解决方法:直接使用事件对象的widget属性

Tkinter事件回调的第一个参数是触发事件的事件对象,其widget属性就对应当前触发事件的控件,不需要额外捕获循环变量,也不需要做name匹配,逻辑最简洁:

from tkinter.scrolledtext import ScrolledText
from tkinter import Tk

root = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (w, h))

for x in range(6):
    # 修复x为整型不能直接拼接字符串的问题
    kiblogbn = ScrolledText(root, name="frm_"+str(x), width=25, height=30, border=2, relief="solid")
    kiblogbn.grid(column=x, row=0, padx=10, pady=10, ipady=25, sticky="W")

    kiblogbn.insert("1.0", 'Copy logs here.')
    # 用e.widget获取当前触发事件的控件
    kiblogbn.bind("<FocusIn>", lambda e: e.widget.delete('1.0', 'end'))
    # get时用end-1c排除控件自带的末尾换行,判断更准确
    kiblogbn.bind("<FocusOut>", lambda e: e.widget.insert("1.0", "Copy logs here.") if e.widget.get("1.0", "end-1c").strip() == "" else None)

if __name__ == "__main__":
    root.mainloop()

可选替代方法:lambda默认参数捕获当前变量

如果你不想用事件对象的属性,也可以通过给lambda设置默认参数的方式,在每次迭代时就把当前控件实例保存下来,避免后续迭代覆盖变量:

# 绑定示例
kiblogbn.bind("<FocusIn>", lambda _, w=kiblogbn: w.delete('1.0', 'end'))
kiblogbn.bind("<FocusOut>", lambda _, w=kiblogbn: w.insert("1.0", "Copy logs here.") if w.get("1.0", "end-1c").strip() == "" else None)

内容的提问来源于stack exchange,提问作者scll.raz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 09:24:03