The problem occurs when a mouse button is pressed and not released, another click event
happens which interrupts the current event
. I will try to show this with the following code example:
import tkinter as tk
root = tk.Tk()
l = tk.Label(bg='red', width=30, height=30)
l.pack(fill='both', padx=100, pady=100)
l.bind('<Button-1>', lambda e: print('pressed'))
l.bind('<ButtonRelease-1>', lambda e: print('release'))
root.mainloop()
To reproduce this error:
root
. The mouse button must remain pressed.Note: In the 4'th step it is important to stay outside the red label
otherwise everything will work.
So for some reason the ButtonRelease-1
event will not happen, most likely because another event happened during the hold process, but it is still not clear for me why.
I want to avoid this. Maybe it is possible to block other events during this process or force other events to work together with this event. I tried to use break
, also tried to use add='+'
for the bind functions, but none of that works.
it doesn't work on windows because windows can only have 1 "window" (AKA widget) capturing the mouse with SetCapture, when you click outside of there the focus shifts from the label (static window) to the main window (TKWindow) and the OS is going to send the WM_LBUTTONUP message to the window instead of the label.
to get around that you could have the parent window handle the mouse event instead of the label, and just check that the mouse is within the bounds of the label, or just live with this problem.
Edit: another way is to block events from all of the system until this action is done as follows.
import tkinter as tk
root = tk.Tk()
l = tk.Label(bg='red', width=30, height=30)
l.pack(fill='both', padx=100, pady=100)
def down(e):
print('pressed')
l.grab_set_global()
def up(e):
print('release')
l.grab_release()
l.bind('<Button-1>', down)
l.bind('<ButtonRelease-1>', up)
root.mainloop()