Seite 1 von 1

Canvas Event

Verfasst: Sonntag 5. April 2009, 21:25
von Pascal
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

Verfasst: Sonntag 5. April 2009, 21:35
von Birne94
unbind aufrufen und dann neu binden...

Verfasst: Sonntag 5. April 2009, 21:40
von Pascal
:? 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

Verfasst: Montag 6. April 2009, 07:07
von wuf
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:

Verfasst: Montag 6. April 2009, 08:48
von Pascal
Vielen Dank!!

Das hilft mir weiter :D

Verfasst: Dienstag 7. April 2009, 13:19
von yipyip
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

Verfasst: Sonntag 12. April 2009, 18:23
von yipyip
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

Verfasst: Donnerstag 30. Juli 2009, 20:08
von Pascal
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.

Verfasst: Donnerstag 30. Juli 2009, 20:24
von EyDu
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.

Verfasst: Donnerstag 30. Juli 2009, 20:58
von Pascal
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?

Verfasst: Donnerstag 30. Juli 2009, 21:08
von EyDu
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).