Seite 1 von 1

Knopf-Event

Verfasst: Donnerstag 11. November 2010, 19:21
von nomnom
Hallo!
Ich möchte mir gerade ein GUI für meine Caesar-Verschlüsselung basteln. Aber immer wenn ich diese starte, kommt das ``tkMessageBox.showinfo()``-Fenster, und bei Klick auf den »Encrypt«-Knopf passiert nichts. Woran liegt das? Wo liegt mein doofer Denkfehler? ;)

Code: Alles auswählen

#!/usr/bin/env python
import caesar
import Tkinter
import ScrolledText
import tkMessageBox

class Application(Tkinter.Frame):
    def create_widgets(self):
        self.shift_input = Tkinter.Entry(self)
        self.shift_input.pack()
        self.shift_content = Tkinter.StringVar()
        self.shift_input['textvariable'] = self.shift_content

        self.textfield = ScrolledText.ScrolledText(self)
        self.textfield.pack()

        self.encrypt_button = Tkinter.Button(self, text='Encrypt')
        self.encrypt_button['command'] = tkMessageBox.showinfo('Shift', self.shift_content.get())
        self.encrypt_button.pack({"side": "left"})

        self.decrypt_button = Tkinter.Button(self, text='Decrypt')
        self.decrypt_button.pack({"side": "left"})

        self.quit_button = Tkinter.Button(self, text='Quit')
        self.quit_button['command'] = self.quit
        self.quit_button.pack({"side": "right"})

    def __init__(self, master=None):
        Tkinter.Frame.__init__(self, master)
        self.pack()
        self.create_widgets()

root = Tkinter.Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
Ist natürlich noch nicht fertig. Mein Problem liegt bei dem hier:

Code: Alles auswählen

        self.encrypt_button['command'] = tkMessageBox.showinfo('Shift', self.shift_content.get())
Sollte diese Box dann nicht erst bei Klick auf »Encrypt« erscheinen? (Ich weiß, »Encrypt« passt zu dem was ich tun will nicht, aber es geht nur darum, um zu sehen wie es funktioniert)

Bei dem funktioniert es ja:

Code: Alles auswählen

        self.quit_button['command'] = self.quit
Viele Grüße,
Jakob.

Re: Knopf-Event

Verfasst: Donnerstag 11. November 2010, 20:53
von Xynon1
Erstens bitte auf optionale Parameter wie "command" in Tkinter mit .config(command=...) ändern.
Zweitens du rufst das Fenster sofort auf, du brauchst aber ein "callback", also nutze ein lambda.

Code: Alles auswählen

        func = lambda: tkMessageBox.showinfo('Shift', self.shift_content.get())
        self.encrypt_button.config(command=func)

Re: Knopf-Event

Verfasst: Donnerstag 11. November 2010, 21:20
von nomnom
Xynon1 hat geschrieben:Erstens bitte auf optionale Parameter wie "command" in Tkinter mit .config(command=...) ändern.
Zweitens du rufst das Fenster sofort auf, du brauchst aber ein "callback", also nutze ein lambda.

Code: Alles auswählen

        func = lambda: tkMessageBox.showinfo('Shift', self.shift_content.get())
        self.encrypt_button.config(command=func)
Danke Xynon1 :-)
Ich dachte es wäre egal, ob man da eine Funktion oder eine nicht-Funktion als Argument angibt. So funktioniert es natürlich super.

Re: Knopf-Event

Verfasst: Donnerstag 11. November 2010, 21:46
von Xynon1
nomnom hat geschrieben:Ich dachte es wäre egal, ob man da eine Funktion oder eine nicht-Funktion als Argument angibt. So funktioniert es natürlich super.
Nein, ist es nicht, nochmal damit du auch wirklich den Hintergrund erfasst, wird dir in Tkinter wie sicherlich in anderen GUIs häufig über den Weg laufen.

Wenn du hinter eine Funktion Klammerst, also (), dann wird die Funktion gerufen.
Das ist nicht wirklich sinnvoll wenn sie bei einer Zuweisung, in welcher die Funktion beim Auslösen gerufen werden soll, schon ausgeführt wird. So bekommt dein "command" nämlich nur den return der Funktion, also bei

Code: Alles auswählen

>>> def a():
...        return 1
>>> b = a()
>>> b
1
>>> # Du brauchst aber die Funktion, also
>>> b = a
>>> b
<function a at 0x89c6fb4>
So wird einfach nur der "callback" der Funktion an "b" gegeben, was zur folge hat das du "b" jetzt mit Klammern rufen kannst.
Wie du vieleicht bemerkt hast macht sich das bei Parametern etwas schwerer, dafür gibt es dann das Keyword "lambda".
Dieses sorgt dafür das eine Funktion zurück gegeben wird.
Folgendes ist zB im prinzip das gleiche:

Code: Alles auswählen

>>> def a(x):
...	    return x * x
>>> a(2)
4
>>> # oder
>>> b = lambda x: x * x
>>> b(2)
4
Und in deinem Script oben machst du nun nichst weiter als

Code: Alles auswählen

>>> c = lambda: a(2)
>>> c()
4

Re: Knopf-Event

Verfasst: Freitag 12. November 2010, 14:20
von nomnom
Vielen vielen Dank, Xynon1. :D
Du hast dir da wirklich viel Mühe gegeben, und habs jetzt verstanden. Ist eigentlich logisch, aber beim Programmieren fällt mir sowas gar nicht auf. :|
Viele Grüße,
Jakob.