使用for循环创建带链接的Tkinter标签时,所有链接指向同一URL的原因
问题原因
你遇到的是Python lambda表达式的延迟绑定问题:循环里的lambda并没有立刻捕获当前循环的data值,而是保存了对data变量的引用。当你点击Label触发事件时,循环已经执行完毕,data指向数据集的最后一项,所以所有Label的点击都会打开最后一个URL。
解决方法
有两种简单的修复方式:
方法1:给lambda添加默认参数绑定当前URL
通过给lambda设置默认参数,让每次循环时把当前的URL值固定下来,而不是引用循环变量:
from tkinter import * import os root = Tk() dataset =[['Google', 'http://www.google.com'], ['Ecosia', 'http://www.ecosia.org'], ['IBM', 'http://www.ibm.com']] def create_links(dataset): docs = [] for i, data in enumerate(dataset): docs.append(Label(root, text=data[0], fg="blue", cursor="hand2")) # 用默认参数url=data[1]绑定当前循环的URL docs[i].bind('<Button-1>', lambda e, url=data[1]: os.system(f'start {url}')) docs[i].pack() create_links(dataset) root.mainloop()
方法2:使用functools.partial绑定参数
如果觉得lambda默认参数不够直观,可以用functools.partial把打开URL的函数和对应参数绑定:
from tkinter import * import os from functools import partial root = Tk() dataset =[['Google', 'http://www.google.com'], ['Ecosia', 'http://www.ecosia.org'], ['IBM', 'http://www.ibm.com']] def open_url(url): os.system(f'start {url}') def create_links(dataset): docs = [] for i, data in enumerate(dataset): docs.append(Label(root, text=data[0], fg="blue", cursor="hand2")) # partial将open_url和当前data[1]绑定 docs[i].bind('<Button-1>', partial(open_url, data[1])) docs[i].pack() create_links(dataset) root.mainloop()
这两种方法都能让每个Label绑定到对应循环项的URL,点击时打开正确的链接。
内容的提问来源于stack exchange,提问作者Holger Hanssen
相关产品推荐
相关产品推荐

