Canvas Event

Fragen zu Tkinter.
Antworten
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

mit ~~ canvas.tag_bind(name, '<Enter>', prozedur) ~~ kann ich ja die prozedur aufrufen, sobald ich mit der Maus auf 'name' komme.

aber das darf genau nur einmal passieren!

wenn ich ein zweites mal darauf komme soll eine andere Prozedur aufgerufen werden.

momentan habe ich dazu gar keine Idee

Bitte helft mir

Edit: Neue Frage dazu: http://www.python-forum.de/post-143238.html#143238
Zuletzt geändert von Pascal am Donnerstag 30. Juli 2009, 20:09, insgesamt 2-mal geändert.
Birne94
User
Beiträge: 90
Registriert: Freitag 28. November 2008, 15:18
Kontaktdaten:

unbind aufrufen und dann neu binden...
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

:? ich bin noch neuling was das programmieren angeht.

deswegen weiß ich nicht genau wie das gehen sollte

trotzdem danke für deine antwort, ein bisschen näher beschreiben wär noch gut

Danke
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hallo Pascal

Hier etwas zum ausprobieren:

Code: Alles auswählen

# Skriptname: canvas_tag_unbind_01_01.py (wuf)

import Tkinter as tk

def square_first_function(event):

    print 'Erste Funktion'

    #~~ Loese die erste Funktion vom Canvas Rechteck-Objekt
    canvas.unbind('rechteck')
    #~~ Binde die zweite Funktion an das Canvas Rechteck-Objekt
    canvas.tag_bind('rechteck', '<Enter>', square_second_function)

def square_second_function(event):

    print 'Zweite Funktion'

app_win = tk.Tk()


canvas = tk.Canvas(app_win, width=200, height=200)
canvas.pack()

square = canvas.create_rectangle(20, 20, 100, 100, fill='steelblue',
    tags='rechteck')

#~~ Binde die erste Funktion an das Canvas Rechteck-Objekt
canvas.tag_bind('rechteck', '<Enter>', square_first_function)

app_win.mainloop()
Gruss wuf :wink:
Take it easy Mates!
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

Vielen Dank!!

Das hilft mir weiter :D
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Hallo Pascal,
wenn Du etwas von Deinem Quellcode zeigen würdest,
könnte man auch etwas gezielter antworten,
aber ich behaupte mal, dass das 'unbind()' nicht
die Lösung Deines Problems darstellt, sondern eher
eine bessere Organisation deines Programmes.

Deine Quadrate wollen anscheinend Identität,
Zustand und Methoden haben, also mache doch eine
Klasse daraus.

Als Beispiel hier ein kleines OO-Konzept:
http://paste.pocoo.org/show/111439/

Bei einem Enter-Event für ein Rechteck wird immer
abwechselnd entweder eine neues zufällig erzeugt
oder das aktuelle neu eingefärbt.

Vielleicht bringt Dich das Beispiel ja etwas weiter.

:wink:
yipyip
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

Da ich nun endlich Deine Aufgabenstellung kenne,
hier nochmal ein 'Proof of Concept' meiner obigen Behauptung.

http://paste.pocoo.org/show/112242/

Mauszeiger auf Rechteck startet einen Countdown,
ist dieser abgelaufen, wird ein neues Rechteck erzeugt,
Mauszeiger auf dieses Rechteck startet Countdown, ist dieser ...
Selbstverständlich wird auch die Reaktionszeit zwischen
altem und neuem Rechteck berechnet.

Jaaa, ich weiss, das ist alles etwas kompliziert
(...jedenfalls fand ich die Aufgabe überhaupt nicht trivial...),
aber vielleicht kannst Du mit der Zeit ja doch noch etwas damit
anfangen.

:wink:
yipyip
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

Ich will diesen Thread mal nutzen, um eine weitere Frage loszuwerden:
Was muss ich tun, wenn ich mit einer for-Schleife mehrere Objekte auf einem Canvas erzeuge und diese dann an verschiedene Funktionen binden will?

Hier ein Bsp.:

Code: Alles auswählen

import Tkinter as tk

def kreis_enter1(e):
     print 'Maus im Kreis'
     print '1'
     canv.itemconfig(k, fill='red')



def kreis_enter2(e):
     print 'Maus im Kreis'
     print '2'
     canv.itemconfig(i, fill='red')


win=tk.Tk()


canv=tk.Canvas(win, width=500, height=500, bg='white')
canv.pack(padx=10, pady=10)

kreise=[]
###erstellen der kreise
for e in range(420,20, -50):
     for i in range(70, 470, 50):
          k=canv.create_oval(i+10, e+10, i-10, e-10, fill='white', outline='grey', \
                             tag='kreis')
          kreise.append(k)

          # variante 1
          canv.tag_bind(k, '<Enter>', kreis_enter1)

###variante 2
##for i in kreise:
##     canv.tag_bind(i, '<Enter>', kreis_enter2)
##

win.mainloop()
Ich wüsste gern, wie es geht, dass bei der Funktion der Kreis, den man "entert", konfiguriert wird.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn du ein komplett neues Thema beginnst, dann solltest du auch einen neuen Thread starten.

Du suchst wohl "functools.partial":

Code: Alles auswählen

from functools import partial

def kreis_enter(e, kreis_id):
     print 'Maus im Kreis'
     print kreis_id
     canv.itemconfig(k, fill='red')

for i in kreise:
     canv.tag_bind(i, '<Enter>', partial(kreis_enter, i))
Mal abgesehen davon, dass dein Beispiel nicht funktioniert, da "k" in den Funktionen nicht bekannt ist. Das kannst du aber, genau wie "kreis_id", einbauen.
Das Leben ist wie ein Tennisball.
Pascal
User
Beiträge: 271
Registriert: Samstag 4. April 2009, 22:18

EyDu hat geschrieben: Du suchst wohl "functools.partial":
:twisted: genau damit habe ich es auch probiert, jedoch ohne Erfolg (Exception wurde ausgelöst) :evil:

Ich habe deine Lösung noch etwas geändert, und jetzt geht alles wunderbar.
das sieht jetzt so aus:

Code: Alles auswählen

def kreis_enter(kreis, xy_parameter): 
     print 'Maus im Kreis' 
     print kreis
     canv.itemconfig(kreis, fill='red')

Code: Alles auswählen

for i in kreise: 
     canv.tag_bind(i, '<Enter>', partial(kreis_enter, i)) 
Wenn ich xy_parameterweg lasse, kommt:

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python26\lib\lib-tk\Tkinter.py", line 1410, in __call__
    return self.func(*args)
TypeError: kreis_enter() takes exactly 1 argument (2 given)
Wie ist das zu verstehen?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hab mich verschrieben. Entweder so:

Code: Alles auswählen

def kreis_enter(kreis_id, e):
     print 'Maus im Kreis'
     print kreis_id
     canv.itemconfig(k, fill='red')

for i in kreise:
     canv.tag_bind(i, '<Enter>', partial(kreis_enter, i))
oder so:

Code: Alles auswählen

def kreis_enter(e, kreis_id):
     print 'Maus im Kreis'
     print kreis_id
     canv.itemconfig(k, fill='red')

for i in kreise:
     canv.tag_bind(i, '<Enter>', partial(kreis_enter, kreis_id=i))
sollte es gehen.

Die Fehlermeldung, welche du bekommst, sagt doch eigentlich alles: Die Funktion erwartet einen Parameter, es werden aber zwei übergeben. Die zwei Parameter ergeben sich einmal aus dem Kreis, welchen du bei partial angibst, und dann noch durch den event (das, was du mit "e" abkürzt).
Das Leben ist wie ein Tennisball.
Antworten