Buttons in Schleife erstellen

Fragen zu Tkinter.
Antworten
AndiArbeit
User
Beiträge: 21
Registriert: Freitag 11. Juli 2014, 13:26

Hallo liebes Pythonforum,

Ich möchte in Python 2.7 in einer Schleife Buttons generieren. Mit den Buttons soll ein Link in einem Browser geöffnet werden. Somit ein Button für jeden Eintrag der Liste. Die Länge de rliste ist allerdings Variabel. Ein Auszug meines Quelltexts sieht folgendermaßen aus.

Code: Alles auswählen

from Tkinter import *
links = ["www.google.de","www.python-forum.de/"] # Meine liste wird automatisch generiert, hier nur Beispielhaft
for link in links :
    Button(command = lambda: webbrowser.open(link)).grid(row = reihe, column = spalte )
Das Problem ist, das jetzt leider bei jedem Button nur der letzte Eintrag der Liste angesprochen wird. Ist mir auch klar, da die lambda Funktion ja jedes mal überschrieben wird.

Hat jemand eine Idee wie ich das Problem lösen kann ?
Danke schonmal im Voraus

Gruß AndiArbeit
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Ungetestet:

Code: Alles auswählen

def createButton(link):
    return Button(command = lambda: webbrowser.open(link))

for link in links :
    createButton(link).grid(row = reihe, column = spalte )
a fool with a tool is still a fool, www.magben.de, YouTube
BlackJack

@AndiArbeit: Das löst man mit `functools.partial()`:

Code: Alles auswählen

for link in links :
    Button(command=partial(webbrowser.open, link).grid(row=reihe,column=spalte)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Oder direkt mit `lambda`:

Code: Alles auswählen

In [8]: from __future__ import print_function

In [9]: funs = [lambda: print(x) for x in "a", "b", "c"]

In [10]: for f in funs: f()
c
c
c

In [11]: funs = [lambda x=x: print(x) for x in "a", "b", "c"]

In [12]: for f in funs: f()
a
b
c
Das Problem ist, dass `x` (oder bei dir `link`) nicht bei der Erstellung des `lambda` gebunden wird. Indem man das ueber einen default-Parameter loest kann man das simulieren.
Ene Uran
User
Beiträge: 125
Registriert: Sonntag 17. September 2006, 20:14
Wohnort: Hollywood

Ich glaube dass partial() einfacher ist zum verstehen ...

Code: Alles auswählen

import webbrowser
# use namespace
import Tkinter as tk
from functools import partial

root = tk.Tk()

# Meine liste wird automatisch generiert, hier nur Beispielhaft
links = ["www.google.de","www.python-forum.de/"]
reihe = 0
spalte = 0
for link in links :
    s = link.split('.')[1]
    cmd = partial(webbrowser.open, link)
    tk.Button(root, text=s, command=cmd).grid(row=reihe, column=spalte)
    reihe += 1

root.mainloop()
Zuletzt geändert von Anonymous am Freitag 11. Juli 2014, 20:44, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Atomkraftwerkaktienbesitzer
Benutzeravatar
pillmuncher
User
Beiträge: 1529
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@Ene Uran: Ich glaube dass enumerate() einfacher ist zum verstehen ...

Code: Alles auswählen

spalte = 0
for reihe, link in enumerate(links):
    s = link.split('.')[1]
    cmd = partial(webbrowser.open, link)
    tk.Button(root, text=s, command=cmd).grid(row=reihe, column=spalte)
In specifications, Murphy's Law supersedes Ohm's.
AndiArbeit
User
Beiträge: 21
Registriert: Freitag 11. Juli 2014, 13:26

Funktioniert :D

Vielen Dank für die schnelle und kompetente Hilfe
Ene Uran
User
Beiträge: 125
Registriert: Sonntag 17. September 2006, 20:14
Wohnort: Hollywood

@pillmuncher, schon richtig, aber reihe muss nicht unbedingt mit null anfangen, kommt auf den Rest der GUI an.
Atomkraftwerkaktienbesitzer
Benutzeravatar
pillmuncher
User
Beiträge: 1529
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ene Uran hat geschrieben:@pillmuncher, schon richtig, aber reihe muss nicht unbedingt mit null anfangen, kommt auf den Rest der GUI an.
Ok:

Code: Alles auswählen

>>> [x for x in enumerate('hallo', start=123)]
[(123, 'h'), (124, 'a'), (125, 'l'), (126, 'l'), (127, 'o')]
In specifications, Murphy's Law supersedes Ohm's.
Antworten