Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Thanks for posting this question and for providing a solution. I can't count how many hours I lost trying to fix up the symptoms created by this behaviour. Weird <code>Tk</code> design decision that <code>tag_bind</code> is insenstive to <code>return "break"</code>.</p> <p>Following your idea to hijack the <code>Text</code> widget by binding it with the same event sequence as <code>tag_bind</code>, I have improved the solution, which <strong>enables now to simulate the expected <code>return "break"</code> behaviour of Tk's other bind+callback pairs</strong>. The idea is the following (full source below):</p> <ol> <li>create a wrapper around the wished <code>callback</code>, i.e. a callable class instance</li> <li>when the class instance is called, run <code>callback</code> and check its result. <ul> <li>if the result is <code>"break"</code>, temporarily hijack the event propagation: <code>bind</code> the <code>Text</code> widget to the same event bound to <code>tag_bind</code>, with an empty callback. Then, after an idle time, <code>unbind</code>.</li> <li>if the result is not <code>"break"</code>: do nothing, the event will propagate to <code>Text</code> automatically</li> </ul></li> </ol> <p>Here is a full working example. My specific problem was to get some sort of <em>hyper text</em> behaviour: ctrl-clicking on a hyper-text should not move the insertion point to the click's location. The example below shows that within the same callback wrapped in <code>tag_bind</code>, we can propagate or not the event to the <code>Text</code> widget, simply by returning <code>"break"</code> or another value.</p> <pre><code>try: # Python2 import Tkinter as tk except ImportError: # Python3 import tkinter as tk class TagBindWrapper: def __init__(self, sequence, callback): self.callback=callback self.sequence=sequence def __call__(self, event): if "break" == self.callback(event): global text self.bind_id=text.bind(self.sequence, self.break_tag_bind) return "break" else: return def break_tag_bind(self, event): global text # text.after(100, text.unbind(self.sequence, self.bind_id)) text.after_idle(text.unbind, self.sequence, self.bind_id) return "break" def callback_normal(event): print "normal text clicked" return "break" def callback_hyper(event): print "hyper text clicked" if event.state &amp; 0x004: # ctrl modifier return "break" # will not be passed on to text widget else: return # will be passed on to text widget # setup Text widget root=tk.Tk() text = tk.Text(root) text.pack() text.tag_config("normal", foreground="black") text.tag_config("hyper", foreground="blue") text.tag_bind("hyper", "&lt;Button-1&gt;", TagBindWrapper("&lt;Button-1&gt;", callback_hyper)) text.tag_bind("normal", "&lt;Button-1&gt;", callback_normal) # write some normal text and some hyper text text.insert(tk.END, "normal text, ", "normal") text.insert(tk.END, "hyper text (try normal-click and ctrl-click).", "hyper") root.mainloop() </code></pre> <p>There is one simplification I couldn't find how to do: replace the wrapper call <code>TagBindWrapper("&lt;Button-1&gt;", callback_hyper)</code> by <code>TagBindWrapper(callback_hyper)</code>, i.e. get the information of the event 'sequence' string (<code>"&lt;Button-1&gt;"</code>) simply from the <code>event</code> object passed to <code>__call__</code>. Is it possible?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload