kharandziuk
kharandziuk

Reputation: 12880

How can I stop raising event in Tkinter?

I have some code like this

from Tkinter import *
master = Tk()
def oval_mouse_click(event):
    print "in oval"
def canvas_mouse_click(event):
    print "in canvas"
w = Canvas(master, width = 800, height = 600)
uid = w.create_oval(390, 290, 410, 310, fill='blue')
w.tag_bind(uid, "<Button-1>", lambda x: oval_mouse_click(x))
w.bind("<Button-1>" , canvas_mouse_click)
w.pack()
mainloop()

When I click on Canvas I have "in canvas" message in console. When I click] on Oval I have two messages "in oval" and "in canvas", but I want to have only first message. Is there any way to stop event raising?

I can do this task with some global flag but I think there should be more natural way for Tkl.

Upvotes: 6

Views: 5278

Answers (2)

armando.sano
armando.sano

Reputation: 380

I have just posted an improved solution on the similar problem there Python tkinter: stopping event propagation in text widgets tags.

The core idea is the same as presented in the previous solutions: hijack the Canvas widget by binding it with the same event sequence as tag_bind. The improved solution I came up with enables now to simulate the expected return "break" behaviour of Tk's other bind+callback pairs. In short:

  1. create a wrapper around the wished callback, i.e. a callable class instance
  2. when the class instance is called, run callback and check its result.
    • if the result is "break", temporarily hijack the event propagation: bind the Canvas widget to the same event bound to tag_bind, with an empty callback. Then, after an idle time, unbind.
    • if the result is not "break": do nothing, the event will propagate to Canvas automatically

The link above lists a full working example with the Text widget, but it is immediately transferable to the Canvas widget.

Upvotes: 3

mmgp
mmgp

Reputation: 19221

Here is the simplest example to handle your issue:

import Tkinter

def oval_mouse_click(event):
    print "in oval"
    event.widget.tag_click = True

def canvas_mouse_click(event):
    if event.widget.tag_click:
        event.widget.tag_click = False
        return
    print "in canvas"

root = Tkinter.Tk()
canvas = Tkinter.Canvas(width=400, height=300)
oid = canvas.create_oval(400/2-10, 300/2-10, 400/2+10, 300/2+10, fill='blue')
canvas.tag_click = False
canvas.tag_bind(oid, "<Button-1>", oval_mouse_click)
canvas.bind("<Button-1>" , canvas_mouse_click)
canvas.pack()
root.mainloop()

There is no other easier way to handle this under Canvas.

Upvotes: 2

Related Questions