Seite 1 von 1
ButtonRelease ist nonstandard
Verfasst: Dienstag 28. August 2012, 13:24
von Goswin
Wahrscheinlich längst bekannt bei tkinter-Benutzern, aber ich bin trotzdem geschockt: das Event ButtonRelease aktiviert das Widget, wo der Button vormals gedrückt wurde, und nicht wo er "released" wird, siehe:
Code: Alles auswählen
import tkinter as t
lb = t.Label(width=20)
lb.pack()
p1 = t.Label(width=10,text='red_paint')
p1.pack()
p1.bind('<ButtonRelease-1>',lambda event: lb.config(bg="red"))
p2 = t.Label(width=10,text='green_paint')
p2.pack()
p2.bind('<ButtonRelease-1>',lambda event: lb.config(bg="green"))
t.mainloop()
Wie kann ich das "richtige" Widget aktivieren, also das, wo der Button losgelassen wird? (wie in anderen gui-Bibliotheken auch, z.B. svg)
Re: ButtonRelease ist nonstandard
Verfasst: Dienstag 28. August 2012, 16:10
von wuf
Hi Goswin
Habe es unter Kubuntu & Windows7 Starter mit Python 3.1 ausprobiert und kann kein Fehlverhalten feststellen. Also drücke ich mit der linken Maustaste auf das Label 'red_pain' passiert nichts. Lasse ich die linke Maustaste los so wird das Label oben rot eingefärbt. Drücke ich dann mit der linken Maustaste auf das Label 'green_paint' passiert nichts. Sobald ich die linke Maustaste loslasse färbt sich das Label oben grün.
Oder verstehe ich dich falsch?
Gruß wuf

Re: ButtonRelease ist nonstandard
Verfasst: Mittwoch 29. August 2012, 08:59
von Goswin
@wuf: Ja, offenbar verstehst du mich falsch.
Drücke einmal mit der linken Maustate auf "red_paint", verschiebe bei gedrückter Maustaste den Zeiger auf "green_paint" (oder sonstwohin) und lasse ihn dann los. Versuche vorher zu erraten, was wohl passieren wird. (Üblicherweise kann man ja, wenn man versehentlich etwas falsch angeklickt hat, das noch bereuen und annulieren, indem man den Mauszeiger vor dem Loslassen aus dem Widget fortbewegt)
Gruß von Goswin

Re: ButtonRelease ist nonstandard
Verfasst: Mittwoch 29. August 2012, 09:20
von deets
Du meinst die Semantik von Tk wenn man Buttons verwendet statt Labels dazu zu missbrauchen?
Code: Alles auswählen
import Tkinter as t
lb = t.Label(width=20)
lb.pack()
p1 = t.Button(width=10,text='red_paint', command=lambda : lb.config(bg="red"))
p1.pack()
p2 = t.Button(width=10,text='green_paint', command=lambda : lb.config(bg="green"))
p2.pack()
t.mainloop()
Re: ButtonRelease ist nonstandard
Verfasst: Mittwoch 29. August 2012, 09:31
von BlackJack
@deets: Das hat überhaupt nichts mit `Button` zu tun. Es geht darum welches Widget-Binding aufgerufen wird, wenn man die Maustaste loslässt. Ich hätte auch erwartet dass es das ist, in dem sich der Mauszeiger zum Zeitpunkt des loslassens befindet. Einfach auf `Button` zu verweisen hilft nicht, denn es gibt Situationen wo man keinen `Button` verwenden kann. Beispiel: man hat einen Canvas auf dem sich bunte geometrische Objekte befinden und der Benutzer soll davon welche anklicken können, mit dem beschriebenen Verhalten, dass die Aktion zum Objekt dann ausgeführt wird, wenn die Maustaste über ihm losgelassen wird.
Re: ButtonRelease ist nonstandard
Verfasst: Mittwoch 29. August 2012, 09:38
von deets
@BlackJack
Jein. Das von Goswin beschriebene Verhalten - die Moeglichkeit, sich "umzuentscheiden" - hat sehr wohl damit zu tun. Auch in allen anderen GUI-Toolkits klickst du auf einen Button, verschiebst den Mauszeiger auf einen *anderen* Button - und bekommst *kein* Button-Release-Event auf dem neuen, noch auf dem alten Button. Und genau dieses Verhalten zeitigt Tk auch, wenn man eben Buttons verwendet.
Dass andere Toolkits mit genrellen Button-Release-Events anders umgehen mag sein. Ich wuerde ja mal versuchen, ob man das ganze durch binden des Button-Release auf dem parent-Widget loesen kann. Theoretisch sollte man ja zumindest ueber die Event-Koordinaten und die View-Hierarchie rauskriegen, wer der Empfaenger sein *sollte*. Ob das praktisch geht kann ich aber nicht wirklich sagen.
Re: ButtonRelease ist nonstandard
Verfasst: Mittwoch 29. August 2012, 09:42
von lunar
@deets Ganz allgemein geht es aber auch darum, dass es der naiven Erwartung vollkommen widerspricht, wenn ein Release-Event in einem Widget ausgelöst wird, über dem der Mauszeiger sich gar nicht befand, als die Maustaste losgelassen wurde.
Re: ButtonRelease ist nonstandard
Verfasst: Mittwoch 29. August 2012, 13:23
von wuf
Hi Goswin
Habe dich effektiv falsch verstanden. Es verhält sich genau so wie du festgestellt hattest. Ich weiss nicht wie dies bei PyQt, wxPython usw. aussieht. Das Snippet von deets mit den Button-Widgets und der 'command'-Option scheint sich richtig zu verhalten. Wenn man mit Tkinter arbeitet sind Überraschungen vorprogrammiert. Da ist man wieder einmal gezwungen in die Gerümpelkammer zu gehen und etwas zusammen zu bauen. Wie es ein Kunstschmied / -Schlosser macht.
Habe es versucht mit etwas Code zu lösen:
Code: Alles auswählen
import tkinter as t
from functools import partial
def change_color(color, event):
xpos = event.x
ypos = event.y
widget_width = event.widget.winfo_width()
widget_height = event.widget.winfo_height()
if xpos <= widget_width and ypos <= widget_height:
lb.configure(bg=color)
lb = t.Label(width=20)
lb.pack()
p1 = t.Label(width=10,text='red_paint')
p1.pack()
p1.bind('<ButtonRelease-1>', partial(change_color, 'red'))
p2 = t.Label(width=10,text='green_paint')
p2.pack()
p2.bind('<ButtonRelease-1>', partial(change_color, 'green'))
t.mainloop()
Funktion ohne Gewähr.
Gruß wuf
