Button Listen Zugriff

Fragen zu Tkinter.
Antworten
pythonjunkie
User
Beiträge: 3
Registriert: Mittwoch 18. März 2020, 21:49

Hey liebe Community,

ich benutze tkinter und möchte gerne mehrere Buttons durch eine for-Schleife erstellen und platzieren und diese direkt auch in eine Liste packen. Ich möchte auf einen Button klicken und ihn markieren lassen (z.b durch Veränderung seiner Background-Color). Mein Problem dabei ist, dass beim Klicken eines bestimmten Buttons immer nur der letzte Button markiert wird. Ich habe mir schon zahlreiche Foren-Einträge zu diesem Problem angeschaut und auch so ziemlich alle Lösungen ausprobiert, doch ich komme immer aufs gleiche hinaus: Es wird immer nur der letzte Button miteinbezogen. Mein Tutor geht stark davon aus, dass es mit der nicht vorhandenen ID-Zuweisung jedes Buttons zusammenhängt. Da ich in diesem Gebiet kein kompletter Python Pro bin, würde ich euch gerne um Rat bitten. :wink:

Mit freundlichen Grüßen
pythonjunkie
Sirius3
User
Beiträge: 18289
Registriert: Sonntag 21. Oktober 2012, 17:20

Ohne Code kann man da wenig sagen, außer dass Du statt lambda functools.partial benutzen mußt.
pythonjunkie
User
Beiträge: 3
Registriert: Mittwoch 18. März 2020, 21:49

Sirius3 hat geschrieben: Mittwoch 18. März 2020, 22:23 Ohne Code kann man da wenig sagen, außer dass Du statt lambda functools.partial benutzen mußt.
import tkinter as tk
root = tk.Tk()
root.title('HUS')
liste=[]

def callback(n):
liste[n].config(bg="red")

for a in range(10):
btn = tk.Button(root, text = a, command = lambda: callback(a))
btn.pack()
liste.append(btn)

root.mainloop()
pythonjunkie
User
Beiträge: 3
Registriert: Mittwoch 18. März 2020, 21:49

Sirius3 hat geschrieben: Mittwoch 18. März 2020, 22:23 Ohne Code kann man da wenig sagen, außer dass Du statt lambda functools.partial benutzen mußt.
import tkinter as tk
from functools import partial
root = tk.Tk()
root.title('HUS')
liste=[]

def callback(n):
liste[n].config(bg="red")

for a in range(10):
btn = tk.Button(root, text = a, command=partial(callback,a))
btn.pack()
liste.append(btn)

root.mainloop()

Mit functools partial funktioniert es endlich. Vielen Vielen Dank :P
Benutzeravatar
__blackjack__
User
Beiträge: 14087
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@pythonjunkie: Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Funktionen und Methoden sollten alles was sie ausser Konstanten benötigen als Argument(e) übergeben bekommen. `callback()` braucht also auch `liste` als Argument.

Allerdings kann man sich fragen warum das so indirekt gelöst ist und `callback()` nicht direkt das jeweilige `Button`-Objekt anstelle des Indexwertes und einer Liste mit allen Schalhflächen bekommt.

`liste` ist kein guter Name weil der nichts darüber sagt was die Bedeutung des Inhalts ist. Wenn man das `Button`-Objekt selbst an `callback()` übergibt, braucht man auch keine Liste von denen. Im Grunde braucht man nicht einmal mehr eine eigene `callback()`-Funktion weil man mit `partial()` auch direkt die `config()`-Methode des jeweiligen `Button` verwenden kann.

`a` ist kein guter Name für den Laufindex. `i`, `j`, und `k` sind da die üblichen Verdächtigen. Und auch Teil der wenigen Ausnahmen wo einbuchstabige Namen akzeptabel sind.

Kryptische Abkürzungen vermeiden: Wenn man `button` meint, nicht `btn` schreiben.

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
from functools import partial


def main():
    root = tk.Tk()
    root.title('HUS')

    for i in range(10):
        button = tk.Button(root, text=i)
        button["command"] = partial(button.config, bg="red")
        button.pack()

    root.mainloop()


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten