2016-11-04 2 views
2

Ich definiere GCanvas, eine Erweiterung von Canvas. Meine Absicht ist es, GCanvas auf Klassenebene zu binden. Es funktioniert nicht.Konfus über Tkinter bind_class

Ich habe auch versucht, an tk.Canvas zu binden und es funktioniert auch nicht. Die Bindung an root oder an die GCanvas-Instanz funktioniert einwandfrei. (Keine dieser Alternativen ist für mich nützlich, aber ich habe sie nur versucht zu sehen, was passiert ist.). Laufendes OS X, El Capitan.

import Tkinter as tk 

class GCanvas(tk.Canvas, object): 

    def __init__(self, master, **kwargs): 
     tk.Canvas.__init__(self, master, kwargs) 

    @staticmethod 
    def enter(e): 
     print "enter", e.widget, e.x, e.y 

    @staticmethod 
    def leave(e): 
     print "leave", e.widget 

    @staticmethod 
    def motion(e): 
     print "motion", e.widget, e.x, e.y 

approach = "bindinstance" 

root = tk.Tk() 
gc = GCanvas(root, width=400, height=300) 
print "root is", root, "gc is", gc 
gc.pack() 

if approach == "bindGCanvas": 
    print "binding to GCanvas" 
    root.bind_class(GCanvas, '<Enter>', GCanvas.enter) 
    root.bind_class(GCanvas, '<Leave>', GCanvas.leave) 
    #root.bind_class(GCanvas, '<Motion>', GCanvas.motion) 
elif approach == "bindCanvas": 
    print "binding to Canvas" 
    root.bind_class(tk.Canvas, '<Enter>', GCanvas.enter) 
    root.bind_class(tk.Canvas, '<Leave>', GCanvas.leave) 
    #root.bind_class(tk.Canvas, '<Motion>', GCanvas.motion) 
elif approach == "bindinstance": 
    print "binding to instance" 
    gc.bind('<Enter>', GCanvas.enter) 
    gc.bind('<Leave>', GCanvas.leave) 
    #gc.bind('<Motion>', GCanvas.motion) 
else: 
    print "binding to root" 
    root.bind('<Enter>', GCanvas.enter) 
    root.bind('<Leave>', GCanvas.leave) 
    #root.bind('<Motion>', GCanvas.motion) 

root.mainloop() 

Antwort

3

Die „Klasse“ in bind_class bezieht sich auf den internen Klassennamen von der tk-Bibliothek verwendet, nicht die Python-Klassennamen. Genauer gesagt, in diesem Zusammenhang bezieht es sich auf eine Bindeetikett, die zufällig derselbe Name wie die Klasse tk ist, die auch zufällig derselbe Name wie eine der Tkinter Kernklassen ist (zB: Toplevel, Canvas, etc).

Um zu GCanvas auf Klassenebene zu binden, wäre die einfachste Sache ein bind Tag GCanvas auf der Leinwand, wie im folgenden Beispiel genannt hinzuzufügen:

class GCanvas(tk.Canvas, object): 
    def __init__(self, master, **kwargs): 
     ... 
     # get the current bind tags 
     bindtags = list(self.bindtags()) 

     # add our custom bind tag before the Canvas bind tag 
     index = bindtags.index("Canvas") 
     bindtags.insert(index, "GCanvas") 

     # save the bind tags back to the widget 
     self.bindtags(tuple(bindtags)) 

Sie dann bind_class wie so verwenden können:

root.bind_class("GCanvas", "<Enter>", GCanvas.enter) 
root.bind_class("GCanvas", "<Leave>", GCanvas.leave) 

weitere Informationen zu binden Tags, diese Antworten zu einigen anderen tkinter Fragen sehen:

+0

Dank! Daher muss ich keine Python-Klasse definieren. Ich muss meinen Leinwänden nur ein einzigartiges Bindtag hinzufügen, oder? – Eduardo

+0

@ Eduardo: richtig. Ich empfehle, eine Klasse zu verwenden, um einen neuen Canvas-Typ zu erstellen, aber genau genommen nicht _need_. –