Button in forschleife mehrfach erzeugen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
detek001
User
Beiträge: 4
Registriert: Mittwoch 30. Juni 2021, 13:41

Hallo zusammen,

ich bin grade dabei eine Lotterie in einer GUI abzubilden. Dafür habe ich zunächst für jede Zahl manuell einen Button erstellt:

button1 = tkinter.Button(Fenster, text="1", bd=20, command=lambda: [switch(button1, 1), zahl(1, button1), print(Spielerzahlen)])

Die Funktionen "switch" und "zahl" bedienen sich an Namen des jeweiligen Button, da dieser beim klicken zum einen verändert werden soll und zum anderen die Zahl den der jeweilige Button abbildet in eine Liste packen.

Diese umsetzung klappt generell nur finde ich das nicht sehr elegant gelöst, also habe ich versucht, es mit einer Forschleife zu lösen:

Buttonerzeugung(y,z):

for i in list(range(1,50)):
Button = tkinter.Button(text=i, bd=20, command=lambda: [switch(Button, i), zahl(i, Button), print(Spielerzahlen)])
Button.grid(row=y, column=z)
z = z+1
if z == 7:
y+=1
z = 0

Diese erstellt zwar alle Buttons, jedoch werden die Funktionen nicht richtig aufgerufen, wenn ich bspw. auf die 25 klicke, wird direkt ein kreuz auf die letzte Zahl "49" gesetzt.

Ich dachte zunächst das liegt daran, dass der Name ja immer gleich bleibt, man vielleicht i in die Deklarierung einbinden könnte, bspw.

Button = ...

so dass für jedem i in der Liste so ein Button erstellt wird, das habe ich aber von der syntax nicht hinbekommen. Ist es aus diesem Grund gar nicht möglich oder liege ich da auf dem Holzweg?

Vielen Dank und ich freue mich auf eure Antworten.

LG
Detek001
detek001
User
Beiträge: 4
Registriert: Mittwoch 30. Juni 2021, 13:41

Ich konnte es grade schon selbst lösen, dank eines anderen Beitrags, mithilfe eines Dictionaries konnte ich nun einen index abbilden.

Dazu habe ich zuerst außerhalb der Schleife ein Dictionary erstellt:

buttons = {}

dieses habe ich dann in der funktion angesprochen:

def Buttonerzeugung(w,x,y,z):
for i in button:
buttons = tkinter.Button(text=i, bd=20, command=lambda i=i: [switch(buttons, int(i)), zahl(int(i), buttons), print(Spielerzahlen)])
buttons.grid(row=y, column=z)
z = z+1
if z == 7:
y+=1
z = 0

vielleicht hilft es jemand anderen weiter.

LG
Detek001
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das hat alles nichts mit dem Dictionary zu tun. Sondern mit dem i=i , welches den Index zum Moment der callback Erzeugung “einfängt”.
Sirius3
User
Beiträge: 18274
Registriert: Sonntag 21. Oktober 2012, 17:20

Alles was eine Funktion braucht, muß sie auch über ihre Argumente bekommen. Benutze keine globalen Variablen.
Wenn Du einen aufsteigenden Index hast, dann ist ein Wörterbuch falsch, dann nimmt man eine Liste.
Was ist `button` denn für ein Objekt?
Funktionen schreibt man wie Variablennamen komplett klein. Funktionen werden nach Tätigkeiten benannt, also erzeuge_buttons.
Statt z und y manuell zu zählen, rechnet man sich aus dem Index row und column einfach aus.
`w` wird gar nicht benutzt.
Eine Liste ist kein Ersatz für eine richtige Funktion. `lambda` ist wirklich nur für einfache Ausdrücke da. Und um Parameter fix zu übergeben, benutzt man functools.partial, statt des Defaultparameter-Tricks.

Code: Alles auswählen

import tkinter
from functools import partial

def click(button, i, spielerzahlen):
    switch(button, i)
    zahl(i, button)
    print(spielerzahlen)

def erzeuge_buttons(spielerzahlen):
    buttons = []
    for i in range(1, 50):
        row, column = divmod(i - 1, 7)
        button = tkinter.Button(text=i, bd=20)
        button['command'] = partial(click, button, i, spielerzahlen)
        button.grid(row=row, column=column)
        buttons.append(button)
    return buttons
detek001
User
Beiträge: 4
Registriert: Mittwoch 30. Juni 2021, 13:41

Hallo Siruis3,

Danke für deine konstruktive Kritik und hilfreichen Lösungen den Code zu optimieren, werde mich mal dran setzen und es versuchen zu implementieren 👍

Lg
Detek001
Antworten