Home > OS >  when tk().event_generate('<Button-1>', x, y) on a top level frame/window does the cl
when tk().event_generate('<Button-1>', x, y) on a top level frame/window does the cl

Time:11-03

I have access to the top level tkinter window, but when I do:

self._root = tk.Tk()
<snip>
x = 10 # in screen coordinates
y = 20 # in screen coordinates
self._root.event_generate('<Button-1>', x=x, y=y)
self._root.event_generate('<ButtonRelease-1>', x=x, y=y)

I expect the button click to be applied to the widget underneath location x,y on the window. In this example a Button.

My understanding is event_generate places an event on the message queue inside tkinter just like a real mouse click would do. Normally clicking anywhere inside a window or a frame, causes the click to go through the top-level panes until it finds a widget with a bind() associated with it, i.e. a Button.

And so using that I should be able to simulate a button click anywhere on the window without moving the actual mouse.

But it doesn't do anything, no click, no error, no anything.

What am I missing?

CodePudding user response:

event_generate is not the same as simulating a click by the user. Instead, you're explicitly specifying the window that is to receive the event.

If you need to simulate the actions of a user, you can use the method winfo_containing which will return the widget at a given coordinate. You can then pass that widget to event_generate.

CodePudding user response:

With @Bryan Oakley's excellent help, I was able to get this to work:

# the top level window
self._root = tk.Tk()  
<snip>
x = 10 # in screen coordinates
y = 20 # in screen coordinates

# get a reference to the widget in the root window that is
# underneath coordinate x,y
w = self._root.winfo_containing(x, y)

# Note: the <Enter> is necessary. Without it the 
# button events don't do anything.
w.event_generate('<Enter>', x=x, y=y)
w.event_generate('<Button-1>', x=x, y=y)
w.event_generate('<ButtonRelease-1>', x=x, y=y)

# The invoke() also works.
# w.invoke()

Note: the widget in this sample is a Button. I have not yet tried this same technique on other widgets e.g. an Entry or RadioButton widget. There may need to be additional event_generate() calls or additional events to make that work.

  • Related