bind未检测到Python Tkinter事件生成

2021-06-13 13:38:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个类(一个称为'Point'一个称为'PointConector'),它们都继承了'Frame'(我不确定是否需要,但正在查看是否有帮助)

当我移动该点(鼠标左/右键)并拖动该点时,我想为“PointConnector”(连接twp点的线)触发一个事件,以拾取该事件并用该点的新位置重新绘制该线。你知道吗

如果我使用从canvas对象生成的事件,并且也从canvas对象绑定,那么事件被拾取,但是传递的对象是canvas对象,而不是Point对象。你知道吗

如果我从Point对象(从Frame继承)触发事件生成,那么该事件将被忽略

我需要bind事件将Widget字段设置为生成事件的'Point'。(我需要知道触发事件的那一点)。因此,事件中的字段“Widget”应该是正在处理的点对象,而不是画布。你知道吗

from tkinter import Tk, Canvas,Frame

class pointConnector(Frame):
    point1 = None
    point2 = None
    connector = None

    def __init__(self,canvas, point1,point2):
        super(pointConnector,self).__init__(canvas)

        self.point1 = point1
        self.point2 = point2
        self.canvas = canvas
        p1 = self.canvas.translatePoint((self.point1.x,self.point1.y))
        p2 = self.canvas.translatePoint((self.point2.x,self.point2.y))

        self.connector = canvas.create_line(p1[0], p1[1], p2[0], p2[1],fill='red',state="hidden", width =2)

        self.canvas.bind("<<foo>>",self.dummy)

    def dummy(self,event):
        print("Virtual Event Data: {}".format(event))

    def show(self):
        self.canvas.itemconfig(self.connector,state="normal")

class screen(Canvas):
    width =0
    height=0
    cY = 0
    cX = 0

    items =[]
    dragItem = None
    mouseOverItem = None

    def setScreenSize(self,width,height):
        self.height = height
        self.width = width
        self.cX = int(width/2)
        self.cY = int(height/2)

    def __init__(self,root, unit,width,height):
        super(screen,self).__init__(root,width=width,height=height)
        self.root = root
        self.width = width
        self.height = height
        self.setScreenSize(width,height)

        self.tag_bind('DRAG_OBJECT','<ButtonPress-1>',self.onStartDrag)
        self.tag_bind('DRAG_OBJECT','<ButtonRelease-1>',self.onEndDrag)
        self.tag_bind('DRAG_OBJECT','<B1-Motion>',self.onDrag)


        self.bind("<Configure>", self.configure)



    def addObject(self,object):
        self.items.append(object)


    def findObject(self,tags):
        for item in self.items:
            if str(item.id) in tags:
                return item
        return None


    def onStartDrag(self,event):
        self.dragItem= self.find_closest(event.x,event.y)
        wt = self.gettags(self.dragItem)
        self.dragItem = self.findObject(wt)

    def onEndDrag(self,event):
        self.dragItem = None

    def onDrag(self,event):
            self.dragItem.move(event.x,event.y)

    def draw(self):
        # Draw array of items
        for o in self.items:
            o.show()

    def translateX(self,x):
        return (x + self.cX)  

    def translateY(self,y):
        return (y + self.cY)  

    def translatePoint(self,pointxy):
        return (self.translateX(pointxy[0]),self.translateY(pointxy[1]))

class point(Frame):

    state = "normal"
    x : int
    y : int
    def setPoint(self,x,y):
        self.x = x
        self.y = y

    def __init__(self,canvas,x,y,radius,ObjectName):
        super(point,self).__init__(canvas)
        self.x = x
        self.y = y
        self.radius = radius
        self.canvas = canvas
        self.ObjectName= ObjectName
        self.id = None
        self.create_point()

    def create_point(self):
        x = self.canvas.translateX(self.x)
        y = self.canvas.translateY(self.y)
        self.circle = self.canvas.create_oval(x-self.radius,y-self.radius,x+self.radius,y+self.radius,state=self.state,fill='yellow')
        self.text = self.canvas.create_text(x,y,text=self.ObjectName,state=self.state )
        self.canvas.itemconfig(self.circle, tags=({"type":"POINT", "name":self.ObjectName},"DRAG_OBJECT"))
        self.canvas.itemconfig(self.text, tags=({"type":"POINT", "name":self.ObjectName},"DRAG_OBJECT"))

        self.id = {"type":"POINT", "name":self.ObjectName}

    def show(self):
        newX = self.canvas.translateX(self.x)
        newY = self.canvas.translateY(self.y)

        self.canvas.itemconfig(self.circle,state='normal')
        self.canvas.coords(self.circle,(newX-self.radius,newY-self.radius,newX + self.radius, newY + self.radius))
        self.canvas.coords(self.text,(newX,newY))

        self.canvas.itemconfig(self.text,state='normal')
        self.canvas.tag_raise(self.circle)
        self.canvas.tag_raise(self.text)

    def hide(self):
        self.canvas.itemconfig(self.circle,state='hidden')
        self.canvas.itemconfig(self.text,state='hidden')

    def move (self,x,y):
        delta_x = x- (self.x + self.canvas.cX)  
        delta_y = y- (self.y + self.canvas.cY) 
        self.canvas.move(self.circle,delta_x,delta_y)
        self.canvas.move(self.text,delta_x,delta_y)
        self.x = x - self.canvas.cX
        self.y = y - self.canvas.cY 

        ## If I use the canvas object (that is passed in) then the Point object picks up the event, but then I cant tell which 'Point' is begin dragged
        #self.canvas.event_generate("<<foo>>",x=self.x,y=self.y,when='now')

        ## If I generate the event from the Point Object then the Event is lost
        self.event_generate("<<foo>>",x=self.x,y=self.y,when='tail')


        self.update()    
# Start of program
print("Start --->")
tk = Tk()
mainScreen = screen(tk,20,700,700)
mainScreen.pack(fill="both",expand=1)

# Add Point A
pointA = point(mainScreen,0,0,10,"A",)
mainScreen.addObject(pointA)

# Add Point B
pointB = point(mainScreen,20,20,10,"B")
mainScreen.addObject(pointB)

LineA = pointConnector(mainScreen,pointA,pointB)
mainScreen.addObject(LineA)

mainScreen.draw()
tk.mainloop()