I am placing labels on a Tab in Tkinter with a for loop. How can I identify in the event handler which label was clicked (or its loop index)? I guess it is functionally similar to a ListBox but without the formatting restrictions. I might want to put the labels in a circle or place them diagonally. I tried finding the coordinates of the label but these are available only if the tab is the first one visible or the tab is redrawn when made active. Also the x, y passed in the event handler is the x, y within the label which does not help to identify the label.
I could copy the label code about 10 times and and have about 10 event handlers. This would work but this is no longer 1970!
Perhaps I could bind a handler to the tab canvas and identify the label from its coordinates. The label would need to be on the first tab or the tab drawn when active.
Perhaps I could create a different event handler for each label by holding the event handlers in an array. I would need an event handler for each label. The code would need to change if the number of labels changed.
I am currently trying a label with ''. Would using buttons with command be easier?
What simple part of Python am I missing? I cannot be the first person to need this! Any help or advice would be appreciated.
CodePudding user response:
You can save a reference to the label text for each label widget in a dict.
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
root.geometry(' 800 50')
notebook = ttk.Notebook(root, width=300, height=200, padding=[10,10,10,10])
notebook.pack()
tab_one = tk.Frame(notebook, bg='wheat')
notebook.add(tab_one, text='Cheese', padding=[10,10,10,10])
tab_two = tk.Frame(notebook, bg='mint cream')
notebook.add(tab_two, text='Misc.', padding=[10,10,10,10])
def clicked(event):
print('Clicked:', name_dict[event.widget])
# Populating Cheese tab with clickable Labels
name_list = ['Cheddar', 'Ilchester', 'Limburger']
name_dict = {}
for index, name in enumerate(name_list):
a = tk.Label(tab_one, width=10, text=name, bg='peru')
a.grid(row=index, column=0, padx=5, pady=5)
name_dict[a] = name # Save references in a dict
a.bind('<Button-1>', clicked)
tk.Label(tab_two, text='Just some text...', bg='powder blue').pack(anchor='nw')
root.mainloop()
Is this what you had in mind?
CodePudding user response:
When you bind events, the function receives an object that includes a reference to the widget that received the event. In the following example, notice how it uses event.widget
to refer to the widget that was clicked on.
import tkinter as tk
def update_label(event):
event.widget.configure(text="You clicked me")
root = tk.Tk()
for i in range(10):
l = tk.Label(root, text="Click me", width=20)
l.pack()
l.bind("<1>", update_label)
root.mainloop()