如何在Tkinter中获取被追踪变量对应的输入框引用
如何在Tkinter中获取被追踪变量对应的输入框引用
这个问题我之前也碰到过,直接解析PY_VARx这种变量名确实不够优雅,而且容易出错。你用lambda的时候遇到的问题,其实是Python闭包的延迟绑定导致的——循环里的row变量在lambda真正执行时,已经变成了循环的最后一个值,而不是你创建每个Entry时的那个row。下面给你几个实用又优雅的解决办法:
方法一:用默认参数捕获循环变量
修改lambda的写法,把当前的row作为默认参数传入,这样每次循环都会把当时的row值绑定到lambda里,避免延迟绑定的问题:
import tkinter as tk from tkinter import ttk DOGS = 3 def main() -> None: root = tk.Tk() root.title('') root.geometry('400x400') dogs = {} entries = {} for row in range(DOGS): dogs[row] = tk.StringVar() # 把row作为默认参数传入lambda,捕获当前循环的row值 dogs[row].trace_add('write', lambda *args, row=row: dog_changed(row, dogs, entries, *args)) entries[row] = ttk.Entry(root, textvariable=dogs[row]) entries[row].grid(row=row, column=0) root.mainloop() def dog_changed(row, dogs, entries, *args): print(f"第{row+1}个输入框发生了变化") print(f"当前内容:{dogs[row].get()}") print(f"对应的输入框对象:{entries[row]}") if __name__ == '__main__': main()
方法二:直接传递输入框对象到回调
如果不需要row索引,直接把Entry对象传给回调函数会更直观:
import tkinter as tk from tkinter import ttk DOGS = 3 def main() -> None: root = tk.Tk() root.title('') root.geometry('400x400') dogs = {} entries = {} for row in range(DOGS): dogs[row] = tk.StringVar() entries[row] = ttk.Entry(root, textvariable=dogs[row]) # 直接把当前创建的Entry传入lambda dogs[row].trace_add('write', lambda *args, entry=entries[row]: dog_changed(entry, *args)) entries[row].grid(row=row, column=0) root.mainloop() def dog_changed(entry, *args): print(f"输入框内容发生变化:{entry.get()}") print(f"对应的输入框对象:{entry}") if __name__ == '__main__': main()
方法三:给StringVar添加自定义属性
你还可以给每个StringVar绑定对应的Entry对象,这样在回调里通过变量就能直接拿到输入框:
import tkinter as tk from tkinter import ttk DOGS = 3 def main() -> None: root = tk.Tk() root.title('') root.geometry('400x400') dogs = {} entries = {} for row in range(DOGS): dogs[row] = tk.StringVar() entries[row] = ttk.Entry(root, textvariable=dogs[row]) # 给StringVar添加自定义属性,绑定对应的Entry dogs[row].linked_entry = entries[row] dogs[row].trace_add('write', lambda *args, root=root: dog_changed(root, *args)) entries[row].grid(row=row, column=0) root.mainloop() def dog_changed(root, *args): # 通过变量名获取对应的StringVar对象 var = root.nametowidget(args[0]) # 获取绑定的Entry entry = var.linked_entry print(f"输入框内容变化:{var.get()}") print(f"对应的输入框对象:{entry}") if __name__ == '__main__': main()
这几种方法都能避免解析PY_VARx这种字符串,而且逻辑清晰,你可以根据自己的需求选择合适的方式~
备注:内容来源于stack exchange,提问作者Psionman
相关产品推荐
相关产品推荐

