Is it possible to make an event fire in a different order. For instance, if I add a MouseWheel
listener to a Text
widget, I will get the event before the scrolling has even been applied. Is there a way to make my bind come last?
import tkinter as tk
root = tk.Tk()
def wheel(event): print('this will fire before the movement has happened')
t=tk.Text(root)
t.pack(fill=tk.BOTH, expand=True)
t.bind('<MouseWheel>', wheel)
root.mainloop()
SIDENOTE: I already have a system where I simply hijack the entire MouseWheel
event and handle the scroll myself. That's not the answer I'm looking for. I seriously want my event to come after it is handled internally.
CodePudding user response:
You can change the order in which callbacks for a specific event are processed, but you can't change the order of the events themselves.
There's already a question on Stackoverflow that asks something similar, and it has an answer that includes an example that illustrates how to change the order that callbacks are handled. See this answer to the question How to bind self events in Tkinter Text widget after it will binded by Text widget?
That answer mentions tkinter's bind tags. There's another question that goes into a bit of detail about how bindings are processed. See this answer to the question Basic query regarding bindtags in tkinter
CodePudding user response:
One method is to create a proxy and filter the events, as below:
import tkinter as tk
from contextlib import suppress
class Text(tk.Text):
def __init__(self, master):
tk.Text.__init__(self, master)
self.bind('<MouseWheel>', self.__handler)
self._p = self._w "_orig"
self.tk.call("rename", self._w, self._p)
self.tk.createcommand(self._w, self._proxy)
def _proxy(self, cmd, *args) -> None:
targ = ""
with suppress(tk.TclError): targ = self.tk.call((self._p, cmd) args)
if cmd=='yview' and 'scroll' in args: self.after_idle(self.__handler, None, args)
return targ
def __handler(self, event, *args) -> None:
if event: print('from bind')
else: print('from proxy')
root = tk.Tk()
t=Text(root)
t.pack(fill=tk.BOTH, expand=True)
root.mainloop()