如何在Tkinter的Text组件中获取点击Label的位置序号?
Tkinter点击Text内Label获取位置序号解决方案
问题描述
在Tkinter中,将Label组件作为子元素添加到Text容器后,能否通过点击Label获取它在Text中的位置序号(而非坐标)?例如存在15个不同的Label,点击第4个Label时,需要返回结果4。
初始实现代码
import tkinter as tk from tkinter import * from tkinter import ttk import re from tkinter.tix import COLUMN from turtle import bgcolor linelist1 = ['some long text 1 as a label!!!', '@combo@Aa Bb Cc Dd', 'some long text 2 as a label!!!', 'some long text 3 as a label!!!', '@combo@Ee Ff Gg Hh', 'some long text 4 as a label!!!'] lines_with_combobox = [e for e, s in enumerate(linelist1) if '@combo@' in s] root = tk.Tk() root.geometry(f'400x100') root.grid_columnconfigure(0, weight=1) root.grid_rowconfigure(0, weight=1) bframe = tk.Frame(root, width=100, height=100, bg='red') bframe.grid(row=0, column=0) text = tk.Text(bframe, wrap="char", background=root.cget("background")) text.pack(fill="both", expand=True) # def get_position(): for line in range(0, len(linelist1)): if line in lines_with_combobox: delete_combo_marker = re.split("@combo@", linelist1[line]) words = delete_combo_marker.pop(0) word_as_values = re.split('\s+', delete_combo_marker[0]) combobox = ttk.Combobox(text, values=word_as_values) text.window_create("end", window=combobox) else: textui = linelist1[line] for word in textui.split(" "): label = tk.Label(text, text=word) # label.bind('<Button-1>', get_position) text.window_create("end", window=label) root.mainloop()
解决方案思路与代码
要实现点击Label获取位置序号,核心是利用Tkinter Text组件的index()方法:将Label组件转为字符串后传入该方法,可得到它在Text中的索引(格式为行号.列号),拆分索引字符串取列号部分,即为该Label在Text中的位置序号。
修改后的完整代码如下:
import tkinter as tk from tkinter import * from tkinter import ttk import re from tkinter.tix import COLUMN from turtle import bgcolor linelist1 = ['some long text 1 as a label!!!', '@combo@Aa Bb Cc Dd', 'some long text 2 as a label!!!', 'some long text 3 as a label!!!', '@combo@Ee Ff Gg Hh', 'some long text 4 as a label!!!'] lines_with_combobox = [e for e, s in enumerate(linelist1) if '@combo@' in s] root = tk.Tk() root.geometry(f'400x100') root.grid_columnconfigure(0, weight=1) root.grid_rowconfigure(0, weight=1) bframe = tk.Frame(root, width=100, height=100, bg='red') bframe.grid(row=0, column=0) text = tk.Text(bframe, wrap="char", background=root.cget("background")) text.pack(fill="both", expand=True) def get_position2(label): # 获取Label在Text中的索引,格式为"行.列" index_str = text.index(str(label)) # 拆分后取列号作为位置序号 position = index_str.split('.')[-1] print(f"点击的Label位置序号:{position}") for line in range(0, len(linelist1)): if line in lines_with_combobox: delete_combo_marker = re.split("@combo@", linelist1[line]) words = delete_combo_marker.pop(0) word_as_values = re.split('\s+', delete_combo_marker[0]) combobox = ttk.Combobox(text, values=word_as_values) text.window_create("end", window=combobox) else: textui = linelist1[line] for word in textui.split(" "): label = tk.Label(text, text=word) # 绑定点击事件,通过lambda传递当前label对象 label.bind('<Button-1>', lambda event, label=label: get_position2(label)) text.window_create("end", window=label) root.mainloop()
关键说明
text.index(str(label)):Text组件的index()方法支持传入子组件的字符串表示,返回其在Text中的位置索引。- Lambda绑定事件:在循环中绑定事件时,需要通过
lambda event, label=label的方式传递当前Label对象,避免循环变量引用问题。 - 位置序号:索引字符串拆分后的列号对应Label在Text中的顺序位置(从0开始计数,若需要从1开始可在输出时加1)。
内容的提问来源于stack exchange,提问作者Kazkuris
相关产品推荐
相关产品推荐

