Koordinaten im Canvas mit tag_bind

Fragen zu Tkinter.
Antworten
Pythonaya
User
Beiträge: 90
Registriert: Sonntag 26. Januar 2003, 11:34
Wohnort: Großbeeren (nahe Berlin)

Samstag 1. März 2003, 16:20

Hi @ all!
Ich habe ein kleines Problem mit TKinter:
Ich möchte ein Label über Events aktualisieren lassen.
Auf dem Label sollen die Koordinaten des mit dem Mauszeiger berührten Rechtecks stehen.

So sieht das Programm bisher aus:

Code: Alles auswählen

from Tkinter import*
def change(koord):
	label.config(text=koord)
root=Tk()
canvas=Canvas(root,width=250,height=250,bg='white')
canvas.pack()
label=Label(root, text='')
label.pack()
i=0
a=0
c=0
liste=[]
while 1:
    name='x'+`a`+'y'+`i`
    name=canvas.create_rectangle(a,i,a+30,i+30)
    canvas.tag_bind(name,'<Enter>',change(name))
    liste.append(name)
    c+=1
    a+=30
    if a==210:
        i=i+30
        a=0
    if i==120:
        break
Wär schön, wenn jemand ne Idee hat. :?

Florian
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Samstag 1. März 2003, 19:01

Hallo!
Pythonaya hat geschrieben:

Code: Alles auswählen

canvas.tag_bind(name,'<Enter>',change(name))
Da liegt der Hund begraben. change() wird bereits beim Aufruf von tag_bind() ausgeführt und der Funktionsaufruf wird durch seinen Rückgabewert ersetzt. Dieses Problem ist eigentlich so die einzige Klippe bei der Tkinter-Programmierung. Du musst also verhindern, dass change() sofort bei der Bindung ausgeführt wird und zwar indem Du den Funktionsaufruf in einen lambda-Ausdruck einbettest:
canvas.tag_bind(name,'<Enter>',lambda event,x=name: change(x))
Nur am Rande: Das event ist nötig, da das 1. Argument einer Event-Callback-Funktion (also lambda) immer das Event-Objekt selbst ist. Da das Event-Objekt hier nicht weiter interessiert, reichen wir es nicht an die Funktion change() weiter. Wäre aber möglich, um zu ermitteln welche Art von Ereignis zu Aufruf der Funktion führte.
Noch was: Du weist name zweimal was zu. Damit 'überbutterst' Du natürlich die erste Zuweisung. So ist es wohl eher in Deinem Sinne:
koord='x'+`a`+'y'+`i`
name=canvas.create_rectangle(a,i,a+30,i+30)
canvas.tag_bind(name,'<Enter>',lambda event,x=koord: change(x))


Jan
Pythonaya
User
Beiträge: 90
Registriert: Sonntag 26. Januar 2003, 11:34
Wohnort: Großbeeren (nahe Berlin)

Sonntag 2. März 2003, 15:00

Der Kumpel, mit dem ich das gestern programmiert habe,
hat einfach alles in eine Klasse geschrieben. Jetzt funktionierts!!!
Aber, danke trotzdem für deine Möglichkeit das Problem zu lösen.

Der Code sieht jeztz so aus:

Code: Alles auswählen

from Tkinter import*


class tags:
    def __init__(self,canvas,name,label,a,i):
        self.canvas=canvas
        self.name2=name
        self.label=label
        self.name=self.canvas.create_rectangle(a,i,a+30,i+30)
    def bind(self):
        self.canvas.tag_bind(self.name,'<Enter>',self.change)
    def change(self,e):
        self.label.config(text=self.name2)
root=Tk()
canvas=Canvas(root,width=240,height=240,bg='white')
canvas.pack()
label=Label(root, text='')
label.pack()
i=0
a=0
c=0
liste=[]
while 1:
    name='x'+`a`+'y'+`i`
    exec 'tag'+str(c)+'=tags(canvas,name,label,a,i)'
    exec 'tag'+str(c)+'.bind()'
    exec 'liste.append(tag'+str(c)+')'
    c+=1
    a+=30
    if a==240:
        i=i+30
        a=0
    if i==240:
        break
Antworten