Python/Tkinter: The order of mouse events different in scrollbar widget

Viewed 311

I'm checking the mouse events when slider dragged by following code. I got different order of mouse event for different widgets.

For Canvas, it looks normal

<ButtonPress-1>
<B1-Motion>
...
<B1-Motion>
<ButtonRelease-1>

for Scrollbar, it looks wrong order

<B1-Motion>
...
<B1-Motion>
<ButtonRelease-1>
<ButtonPress-1>
from tkinter import *

def start(event):
    print('<ButtonPress-1>')

def stop(event):
    print('<ButtonRelease-1>')

def motion(event):
    print('<B1-Motion>')

root = Tk()

canv = Canvas(width=600, height=400, scrollregion=(0, 0, 1200, 800))
canv.grid(row=0, column=0)
scrollY = Scrollbar(orient=VERTICAL, command=canv.yview)
scrollY.grid(row=0, column=1, sticky=N+S)
scrollX = Scrollbar(orient=HORIZONTAL, command=canv.xview)
scrollX.grid(row=1, column=0, sticky=E+W)
canv['xscrollcommand'] = scrollX.set
canv['yscrollcommand'] = scrollY.set

root.bind("<ButtonPress-1>", start)
root.bind("<ButtonRelease-1>", stop)
root.bind("<B1-Motion>", motion)

root.mainloop()

My question is why the order of mouse events for Scrollbar widget is wrong ? the same problem for slider drag and arrowheads click. Can it be set to normal as time sequence ? or can I just bypass the events after scrollbar actions done for slider drag or arrowheads click ?

Environment:

  1. WIN10
  2. Python 3.8.3
  3. Tkinter TkVersion 8.6
1 Answers

I'm actually not sure why this works, but with ttk it works fine. I assume there is something like wait_var() in the background and the variable just changes after the Button is released.

from tkinter import *
from tkinter import ttk

def start(event):
    print('<ButtonPress-1>')

def stop(event):
    print('<ButtonRelease-1>')

def motion(event):
    print('<B1-Motion>')

root = Tk()

canv = Canvas(width=600, height=400, scrollregion=(0, 0, 1200, 800))
canv.grid(row=0, column=0)
scrollY = ttk.Scrollbar(orient=VERTICAL, command=canv.yview)
scrollY.grid(row=0, column=1, sticky=N+S)
scrollX = ttk.Scrollbar(orient=HORIZONTAL, command=canv.xview)
scrollX.grid(row=1, column=0, sticky=E+W)
canv['xscrollcommand'] = scrollX.set
canv['yscrollcommand'] = scrollY.set

root.bind("<ButtonPress-1>", start)
root.bind("<ButtonRelease-1>", stop)
root.bind("<B1-Motion>", motion)

root.mainloop()
Related