Tkinter Button command= mit Parameter?
Hallo Community,
ich bin gerade dabei, ein Programm zu schreiben, welches die Elemente einer Liste ausliest und für jedes Element einen Button erstellt, welcher eine Funktion mit Parameter aufruft. Hier der Codeabschnitt:
global cnt
cnt=open(".\\Actions\\config\\email\\adresses.mail").read().split("\n")
x=20
y=60
maillist=[]
cter=0
for mailf in (cnt):
print(mailf)
maillist.append(cnt.index(mailf))
globals()[f"var{cter}"]=tkinter.Button(root, text=mailf, bg="#222222", fg="#ffffff", command=lambda: om1(mailf))
globals()[f"var{cter}"].place(x=x, y=y)
tkinter.Button(root, text=mailf, bg="#222222", fg="#ffffff", command=lambda: om1(maillist[cter])).place(x=x, y=y)
cter+=1
y+=40
if(r_geometry_y<y):
r_geometry_y+=40
root.geometry(f"300x{r_geometry_y}+800+300")
Leider wird, egal auf welchen Button ich klicke, der Funktion om1 immer der Wert übergeben, der als letztes in der Variable mailf gespeichert war. Was muss ich verändern, damit jeder Button immer den Parameter übergibt, der zum Zeitpunkt der Erzeugung des Buttons in mailf gespeichert war? (Die Länge der Liste wird erst zur Laufzeit bestimmt, also kann ich keine feste Anzahl an Buttons anlegen)
1 Antwort
Deine Lambdas beziehen sich auf eine Variable aus dem for-Scope. Da die mit jeder Iteration geändert wird, hast du später auch nicht mehr den Wert in ihr, den sie bei Kapselung im Lambda hatte.
Eine Lösung wäre die Wertübergabe in eine neue Variable, die im Lambda-Scope liegt.
Beispiel:
lambda fixed_value=value: print(fixed_value))
Wieso du im Übrigen keine einfache Liste zur Speicherung deiner Buttons verwendest und dir stattdessen irgendwelche globablen Variablen zusammenbaust, kann ich nicht nachvollziehen. Ebenso ist die Art, den Schleifenindex mitzuzählen, nicht der übliche Python-Weg.
Ich habe einmal ein kürzeres Skript angelegt, aus dem du Verbesserungsvorschläge ziehen kannst:
import tkinter
def say_hello(name):
print("Hello", name)
with open("person_list.txt", "r") as file:
persons = [line.rstrip() for line in file]
x = 20
y = 20
root = tkinter.Tk()
person_buttons = []
for index, person in enumerate(persons):
print(index)
button = tkinter.Button(root, text=person, command=lambda name=person: say_hello(name))
button.place(x=x, y=y)
person_buttons.append(person)
y += 40
tkinter.mainloop()
Sollte deine Datei sehr viele Zeilen beinhalten, wäre es besser, sie in einer klassischen Schleife zeilenweise einzulesen:
persons = []
with open("person_list.txt", "r") as file:
for line in file:
persons.append(line.rstrip())