Python dictionary, list and for-loop bug
Question:
I’m trying to show a list of elements from a data set in a tkinter window. I want to able to manipulate the elements, by highlighting, deleting etc.
I have this code:
from tkinter import *
window = Tk()
window.geometry("100x100")
#data from API
data_list = [
["1", "Lorem"],
["2", "Lorem"],
["3", "Lorem"],
["4", "Lorem"]
]
#create selectable rectangles from data_list with delete buttons
rectangles = {}
delete_buttons = {}
def CreateRectangles():
i = 0
for data in data_list:
rectangles[i] = Canvas(window, bg="#BFBFBF", height=15, width=80)
rectangles[i].place(x=19, y=20.0 + (i * 19))
rectangles[i].create_text(5.0, 1.0, anchor="nw", text=str(f'#{data[0]}:{data[1]}'))
delete_buttons[i] = Label(window, text="X ", bg="#D9D9D9")
delete_buttons[i].place(x=6, y=20.0 + (i * 19))
i += 1
CreateRectangles()
#highlight clicked rectangle
def RectangleClick(e, arg):
#reset how all rectangles look
for i in rectangles:
rectangles[i].config(bg="#BFBFBF")
#highlight the one clicked
rectangles[arg].config(bg="#999999")
for key in rectangles:
rectangles[key].bind("<ButtonPress-1>", lambda event, arg=key: RectangleClick(event, arg))
#delete button action
def DeleteClick(e, arg):
# delete all rectangles and buttons from window
for rectangle in rectangles:
rectangles[rectangle].place_forget()
for delete in delete_buttons:
delete_buttons[delete].destroy()
# delete all rectangles and buttons from dictionary
rectangles.clear()
delete_buttons.clear()
# delete the specific data from de data_list
data_list.pop(arg)
# re do everything but now the data list has one less item
CreateRectangles()
for num in delete_buttons:
delete_buttons[num].bind("<ButtonPress-1>", lambda event, arg=num: DeleteClick(event, arg))
window.mainloop()
It only works the first time. For example, if I delete an item, it doesn’t do anything else.
What’s wrong?
Answers:
Move all the code that binds event handlers inside the CreateRectangles
method. Since all the previous rectangles are destroyed, the event handlers need to be attached again.
I’m trying to show a list of elements from a data set in a tkinter window. I want to able to manipulate the elements, by highlighting, deleting etc.
I have this code:
from tkinter import *
window = Tk()
window.geometry("100x100")
#data from API
data_list = [
["1", "Lorem"],
["2", "Lorem"],
["3", "Lorem"],
["4", "Lorem"]
]
#create selectable rectangles from data_list with delete buttons
rectangles = {}
delete_buttons = {}
def CreateRectangles():
i = 0
for data in data_list:
rectangles[i] = Canvas(window, bg="#BFBFBF", height=15, width=80)
rectangles[i].place(x=19, y=20.0 + (i * 19))
rectangles[i].create_text(5.0, 1.0, anchor="nw", text=str(f'#{data[0]}:{data[1]}'))
delete_buttons[i] = Label(window, text="X ", bg="#D9D9D9")
delete_buttons[i].place(x=6, y=20.0 + (i * 19))
i += 1
CreateRectangles()
#highlight clicked rectangle
def RectangleClick(e, arg):
#reset how all rectangles look
for i in rectangles:
rectangles[i].config(bg="#BFBFBF")
#highlight the one clicked
rectangles[arg].config(bg="#999999")
for key in rectangles:
rectangles[key].bind("<ButtonPress-1>", lambda event, arg=key: RectangleClick(event, arg))
#delete button action
def DeleteClick(e, arg):
# delete all rectangles and buttons from window
for rectangle in rectangles:
rectangles[rectangle].place_forget()
for delete in delete_buttons:
delete_buttons[delete].destroy()
# delete all rectangles and buttons from dictionary
rectangles.clear()
delete_buttons.clear()
# delete the specific data from de data_list
data_list.pop(arg)
# re do everything but now the data list has one less item
CreateRectangles()
for num in delete_buttons:
delete_buttons[num].bind("<ButtonPress-1>", lambda event, arg=num: DeleteClick(event, arg))
window.mainloop()
It only works the first time. For example, if I delete an item, it doesn’t do anything else.
What’s wrong?
Move all the code that binds event handlers inside the CreateRectangles
method. Since all the previous rectangles are destroyed, the event handlers need to be attached again.