Seite 1 von 1
Lambda
Verfasst: Sonntag 25. Mai 2014, 12:42
von HardwareManager
Ich will ein Programm mit Tkinter machen das mehrere Buttons hat und jeder soll eine andere wirkung haben. Ich versuche es gerade mit lambda weil es muss ja nur
das ausführen wobei es aber nichts macht.
g() ist
aber wenn ich auf den Button klicke dann passiert nichts
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 13:01
von derdon
Code: Alles auswählen
>>> g = lambda x: x + 1
>>> g(1)
2
>>> g
<function <lambda> at 0x1207230>
g ist eine Funktion. Wenn du g(1) aufrufst, bekommst du keine (neue) Funktion zurück, sondern den Rückgabewert von g, wenn es mit dem Argument 1 aufgerufen wurde (in dem Fall 2). tk.Button erwartet aber eine Funktion als `command`-Parameter. Was kann man also machen? Die Frage ist, was für eine Funktion du übergeben möchtest: Soll sie einen Parameter erwarten und den übergebenen Wert um eins erhöht zurückgeben? Dann übergib einfach g, also: ``button = tk.Button(root, text = "test", command=g)``. Oder soll die Funktion keinen Parameter erwarten und in jedem Fall 2 zurückgeben? Das kannst du entweder mit einem weiteren lambda erledigen oder, noch viel besser, mit functools.partial:
Code: Alles auswählen
>>> lambda: g(1)
<function <lambda> at 0x13f71b8>
>>> (lambda: g(1))()
2
>>> from functools import partial
>>> f = partial(g, 1)
>>> f
<functools.partial object at 0x13765d0>
>>> f()
2
In deinem Fall siehe das dann so aus: ``button = tk.Button(root, text = "test", command=partial(g, 1))``
Mir fehlt die Erfahrung mit Tkinter um sagen zu können, was du in deinem Fall brauchst.
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 13:14
von BlackJack
Um dann noch die Erfahrung bezüglich Tkinter ins Spiel zu bringen: Was die Funktion die als `command` übergeben wird als Rückgabewert hat ist vollkommen egal weil das Tkinter nicht interessiert. Der Wert wird einfach ignoriert. Also selbst wenn man die Funktion richtig definiert und übergibt, sieht man da nirgends einen Effekt, solange die Funktionen keinen Effekt hat sondern nur einen Rückgabewert.
Ich denke hier sollte man besser objektorientierte Programmierung lernen und mit dem Wissen ausgestattet dann eine entsprechende Klasse schreiben und bei `command` eine Methode übergeben die dann den Zustand des Objekts so ändert, dass man nach dem Druck auf die Schaltfläche auch den Effekt davon sehen und verwenden kann.
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 13:17
von HardwareManager
DAnke für die schnelle Antwort! Ich dachte lambda setzt die variable neu x neu!
Weil da sollen noch 8 andere Buttons hin die X auch größer machen. Der 1. Button um 1, der 2. Button um 2 usw
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 13:32
von cofi
Wie soll denn `x` veraendert werden, wenn da ueberhaupt keine Zuweisung ist?
Aber selbst mit `x += 1` funktioniert das nicht, weil `x` ein lokaler Name ist.
Was du willst ist was BlackJack schon angedeutet hat: Ein Objekt, dass dein `x` als Attribut speichert und eine Methode zum erhoehen hat, die du dann als `command` uebergibst.
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 14:13
von BlackJack
Mal als kleines Beispiel:
Code: Alles auswählen
import Tkinter as tk
from functools import partial
class CounterFrame(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.value = 0
self.value_label = tk.Label(self)
self.value_label.pack()
button_frame = tk.Frame(self)
for i in xrange(1, 6):
tk.Button(
button_frame, text=str(i), command=partial(self.increase, i)
).pack(side=tk.LEFT)
button_frame.pack()
self._update_value_display()
def _update_value_display(self):
self.value_label['text'] = str(self.value)
def increase(self, amount):
self.value += amount
self._update_value_display()
def main():
root = tk.Tk()
counter = CounterFrame(root)
counter.pack()
root.mainloop()
if __name__ == '__main__':
main()
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 15:24
von HardwareManager
mein Programm sieht aber im moment so aus:
Code: Alles auswählen
from tkinter import *
import tkinter as tk
x = 0
def GUI():
while x == 0:
root = Tk()
w = Canvas(root, width=500, height=500)
w.pack()
button = Button(root, text = "b1", command=b1())
button.place(x=100,y=100)
button = Button(root, text = "b2", command=b2())
button.place(x=150,y=100)
button = Button(root, text = "b3", command=b3())
button.place(x=200,y=100)
button = Button(root, text = "b4", command=b4())
button.place(x=100,y=150)
button = Button(root, text = "b5", command=b5())
button.place(x=150,y=150)
button = Button(root, text = "b6", command=b6())
button.place(x=200,y=150)
button = Button(root, text = "b7", command=b7())
button.place(x=100,y=200)
button = Button(root, text = "b8", command=b8())
button.place(x=150,y=200)
button = Button(root, text = "b9", command=b9())
button.place(x=200,y=200)
return x
def b1():
global x
x += 1
def b2():
global x
x += 2
def b3():
global x
x += 3
def b4():
global x
x += 4
def b5():
global x
x += 5
def b6():
global x
x += 6
def b7():
global x
x += 7
def b8():
global x
x += 8
def b9():
global x
x += 9
print(GUI())
und so soll es in etwa am Ende auch aussehen
aber ich weis nicht wie ich 2 befehle in einen Button packe.
Und ein anderes Problem ist Wenn ich auf einen Button klicke verändert sich die zahl nicht die Zahl bleibt immer auf 45 was die summe von allem ist.
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 15:28
von mutetella
HardwareManager hat geschrieben:und so soll es in etwa am Ende auch aussehen
Dann ist doch alles gut, oder?
HardwareManager hat geschrieben:aber ich weis nicht wie ich 2 befehle in einen Button packe.
Das weiß wahrscheinlich niemand...
HardwareManager hat geschrieben:Und ein anderes Problem ist Wenn ich auf einen Button klicke verändert sich die zahl nicht die Zahl bleibt immer auf 45 was die summe von allem ist.
Dann solltest Du vielleicht doch von Deinem Code Abschied nehmen und Dir BlackJack's Beispiel anschauen und verstehen...
mutetella
Re: Lambda
Verfasst: Sonntag 25. Mai 2014, 16:15
von BlackJack
@HardwareManager: Wenn das *so* aussehen soll, dann kann man Dir nicht wirklich helfen.
Edit: Tipp: Solange da noch `place()` und ``global`` drin sind, ist das nichts vernünftiges.