Button Command

Fragen zu Tkinter.
Antworten
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Ich hab da mal ne Frage: Wie heißt die Funktion, die durch das Klicken auf einen Button aufgerufen wird, um dann die gekoppelte Funktion aufzurufen?? Gibt es so eine überhaupt? Wenn nein, könnt ihr mir sagen, wie das sonst aufgebaut ist?

Edit: Verständnis der Frage verbessert (-;
BlackJack

@Newcomer: Ich verstehe die Frage nicht so ganz. Die Funktion die man als `command` angibt, wird von irgendeiner Funktion oder Methode aus der `Tkinter`-Implementierung aufgerufen. Warum willst Du wissen wie die heisst? Das ist doch egal!?
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@Newcomer
Es ist immer noch nicht besser zu verstehen :|
Meinst du vieleicht lambda oder partial - auf was willst du denn überhaupt hinaus?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Naja, ich meine das so: Wenn ich auf ein Button drücke, dem eine eine Methode zugeordnet ist, so wird diese Methode ausgeführt. Aber wie weiß der Button, dass er diese Methode auf knopfdruck ausführen soll, sprich es muss eine Methode in der Button-klasse geben, die 1. nach der dem Button zugeordneten Methode sucht, und 2. diese dann ausführt. Das habe ich gemeint
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Newcommer

Meinst du so etwas?:

Code: Alles auswählen

import Tkinter as tk

def button_func():
    print "Du hast mich gerufen?"
    
app_win = tk.Tk()

button = tk.Button(app_win, text='Button', command=button_func)
button.pack()

app_win.mainloop()
Gruß wuf :wink:
Take it easy Mates!
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Ja indirekt, das kannte ich schon. Ich meinte innerhalb der Button-Class muss irgendeine methode das event "klick" prüfen. Und von der will ich den Namen. Ich benötige diesen Methodennamen, da ich die Methode selber etwas verändern will
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hast du schon einmal in Tkinter.py rumgeschnüffelt 'class Button', 'class Misc' usw.. (Möchtest du den Wrapper umschreiben?)

Gruß wuf :wink:
Take it easy Mates!
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Perfekt, danke hab nur in der Buttonklasse nachgeschaut. Hab gar nicht drangedacht in misc auch zu schauen. Dort hab ich schließlich gefunden was ich wollte ( Funktion: getint_event)
Edit: Nein ich ihn nicht umschreiben, möchte nur einen MegaButton erstellen, der alle Buttons in sich vereint (-: :twisted: :twisted:
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Ich verstehe es immer noch nicht?! Was nutzt dir diese Information "getint_event" versucht nur einen String in einen Integer-Wert umzuwandeln. Das ist deshalb nötig weil Tkinter ein Wrapper ist und mit dem Tcl-Interpreter nur in Form von Strings kommunizieren kann. Darum bekommt "_substitute" die gesamten Eventdaten aus einer aufbereiteten Stringkette, diese Daten werden dann der Python-Klasse "Tkinter.Event" zugeordnet und der Datentyp gleich richtig gesetzt. Also wie hilft "getint_event" dir da ?

Falls du es nicht Wissen solltest Tk hat ein Event-System in dem per <bind> gearbeitet wird, so ist auch der Button implementiert. Siehe z.B. den Studbutton in Tkinter.py. Wenn du den normalen Button sehen willst, musst du dir den Tcl-Skript für den Button ansehen. Hier ein kleiner Ausschnitt

Code: Alles auswählen

bind Button <Leave> {
    tk::ButtonLeave %W
}
bind Button <1> {
    tk::ButtonDown %W
}
bind Button <ButtonRelease-1> {
    tk::ButtonUp %W
}

bind Checkbutton <FocusIn> {}
bind Checkbutton <Leave> {
    tk::ButtonLeave %W
}

bind Radiobutton <FocusIn> {}
bind Radiobutton <Leave> {
    tk::ButtonLeave %W
}
Allerdings verstehe ich auch noch nicht was ein MegaButton sein soll und was dieser können müsste, aber lass dir eins gesagt sein:
The Zen of Python hat geschrieben:Explicit is better than implicit.
Simple is better than complex.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Na ja pass auf: Ich denke du verstehst mich immer noch nicht, aber meine Frage hat sich schon erledigt, weil ich diese Funktion (und ein paar andere) gefunden habe. Und ein MegaButton soll eine Klasse sein, die alle anderen Button Klassen in sich vereint. Ich dachte da an sowas:

Code: Alles auswählen

Megabutton(main,type_button...)
BlackJack

@Newcomer: Das man Dich nicht versteht, könnte daran liegen, dass Du es nicht wirklich erklärst. ;-) Was ist das für eine Vereinigung? Die Eigenschaften von verschiedenen Button-Typen? Und was ist wenn die sich widersprechen? Gibt es ausser `Tkinter.Button` denn überhaupt noch andere Button-Klassen? Oder meinst Du Exemplare und nicht Klassen? Und was ist *davon* dann eine Vereinigung? Wenn man den Megabutton drückt, werden alle anderen auch gedrückt? Also zum Beispiel ”Ok” und ”Cancel” *gleichzeitig*!?

Und warum musst Du dafür in den Innereien von `Tkinter` rumwühlen? Wenn Du einen neuen Button-Typ haben möchtest, dann erweitere einfach den vorhandenen durch eine Unterklasse.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@Newcomer
Habe ich das jetzt richtig verstanden? Du möchstest statt:

Code: Alles auswählen

bt = Button(master)
cbt = CheckButton(master)
rbt = RadioButton(master)
sbt = StudButton(master)
#...
bspw. folgendes schreiben:

Code: Alles auswählen

mb = MegaButton(master, "CheckButton")
oder wie ist das zu verstehen?

Das kann man z.B. auch so machen:

Code: Alles auswählen

import Tkinter
#...
button = getattr(Tkinter, "CheckButton")
mb = button(master)

bzw. das ganze noch schick in einer Funktion verpacken, aber wozu musst du für diese Implementierung an die Tk[inter] interne herran?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Ja du hast es verstanden (sorry wegen meinen schlechten Formulierungen)!!! Die Methode kannte ich noch nicht mit getattr. Ich zog Tkinter deshalb heran, da ich der Option "command" einen Parameter übergeben wollte. Das hat nicht so ganz geklappt. Ich wollte wissen, wie die Funktion die commadn übergeben wird, aufgerufen wird. Da ich dergleichen nicht gefunden habe, habe ich das jetzt ander versucht:

Code: Alles auswählen

from tkinter import *





class MegaVar(StringVar):
    def __init__(self):
        StringVar.__init__(self)
        self.container =[]
    def seed(self,button):
        if len(self.container) >=1:
            self.container = []
        self.container.append(button)

    def seed_get(self):
        
        return self.container
        
        
        
        

class MegaButton(Button):
    def __init__(self,main,zähler,figur_ja,bg=None,width=10,height=10,command=None,var=None):
        Button.__init__(self,main,bg=bg,width=width,height=height,command=None)
        self.index=False
        self.zähler=zähler
        self.figur_ja=figur_ja
        self.var=var
        self.bind("<ButtonPress>",self.callback_start)
        self.bind("<ButtonRelease>",self.callback_end)
        self.command=command
    def get_counter(self):
        return self.zähler

    def get_stand(self):
        return self.figur_ja

    def callback_end(self,*dummy):
        self.command()
    def callback_start(self, *dummy):
        self.var.seed(self)
        
        
        
        
        
        
        
# Test funktion 
def con():
    global c
    
    k=c.seed_get()
    try:
        
        k[0].config(bg="blue")
    except IndexError:
        pass
# Test

a=Tk()
c=MegaVar()
o=list()
for i in range(50):
    
    b=MegaButton(a,1,False,command=con,var=c)
    o.append(b)
    b.pack()







a.mainloop()
BlackJack

@Newcomer: Das sieht alles sehr eigenartig aus. Beide Klassen scheinen die Oberklasse nicht wirklich zu benötigen. Von `MegaVar` wird anscheinend überhaupt nicht verwendet, dass es ein `StringVar`-Objekt ist und bei dem `MegaButton` wird vom `Button` das `command` nicht verwendet und die Reaktionen auf die Maus werden überschrieben so dass man sich fragen muss, warum das überhaupt von einem `Button` erbt.

Was soll `MegaVar.container`? Eine Liste die maximal ein Element enthält, erscheint mir sehr merkwürdig und so wie es da verwendet wird, auch umständlich. Triviale Getter-Methoden sind ”unpythonisch”. `get_seed()` und `get_counter()` kann man einfach weglassen beziehungsweise bei `seed` durch ein `property()` ersetzen. Falls diese komische Liste mit Länge ≤ 1 wirklich sein muss.

``global`` sollte man nicht verwenden — ist hier auch völlig unnötig. Allerdings sollte man in Funktionen auch nicht auf Werte zugreifen die auf Modulebene liegen aber keine Konstanten sind.

Ich sehe bei dem Beispiel nicht wirklich, dass man dafür einen eigenen `Button`-Typ benötigt. Oder übersehe ich etwas? Was genau soll das denn darstellen?

Der Sternchen-Import ist auch unschön. Bei `tkinter` ist ein Import, der den Namen auf `tk` kürzt üblich. Die Leerzeilen sind ein wenig üppig, dafür könnten mehr Leerzeichen verwendet werden. Die Funktionssignatur von `MegaButton.__init__()` ist zum Beispiel schwer lesbar so zusammen gequetscht.

So grundsätzlich vom Effekt her sollte das hier doch zumindest etwas sehr ähnliches machen, oder?

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import tkinter as tk
from functools import partial


def main():
    root = tk.Tk()
    
    last_button = None
    
    def command(button):
        nonlocal last_button
        last_button = button
        button['bg'] = 'blue'
    
    for i in range(10):
        button = tk.Button(root, width=5, height=5)
        button['command'] = partial(command, button)
        button.pack()

    root.mainloop()


if __name__ == '__main__':
    main()
Newcomer
User
Beiträge: 131
Registriert: Sonntag 15. Mai 2011, 20:41

Ja stimmt, sowas sollte mein skript darstellen. Es ist aber noch ziemlich unfertig und ich wollte die StirngVar (ich denke ich hätte lieber die Elternklasse vererben sollen) noch gebrauchen. Außerdem wollte ich die Klassen noch erweitern und ein paar andere Elemente hinzubauen. Im übrigen weiß ich, dass mien skript nicht das beste ist (-: Ich kenn halt nicht so viele möglichkeiten, dann benutze ich die, die mir als erste durch den kopf schwirren
Antworten