Search code examples
pythoneventstkinterpython-3.6

Tkinter event for DownPress of mouse button (holding down)?


UPDATE: This seams to be a version issue. The event does not fire on click for python 3.6.1 but works on 2.7 that I have tested so far.

UPDATE: Bryan's answer did fix my problem with the event not working correctly however the issue of the event not firing on the down-click not work is still an issue on my 3.6.1 version of python.

Python version = 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)]

I am trying to write an event handler to do something repeatedly while the mouse button is being held down. I have been scouring the documentation and the internet but I cannot find any reference to just holding down the left mouse button.

Is there an event specifically for holding down the left mouse button? There is an even for release <ButtonRelease-1> but there does not seam to be one for a click and hold event.

I have tried <Button-1> and all of its synonymous events just in case but no luck. The event only fires on release but not on the down click as I want it. I don't even need an event for constantly holding the button I just need an even for the down press only.

Documentation welcome as I can't seam to find any.

UPDATE:

Here is an example code. It will only print when the button is released. Keep in mind I am trying to press the arrow buttons on the scroll bar and to change the speed of scrolling.

Does the scrollbar handle pressing the scroll arrows differently than a button?

import tkinter as tk


root = tk.Tk()

textbox = tk.Text(root, height = 10)
textbox.grid(row=0, column=0)

scrolling = False
yscroll = tk.Scrollbar(root, command=textbox.yview,orient="vertical", repeatinterval=10, repeatdelay=30)
textbox.configure(yscrollcommand = yscroll.set)
yscroll.grid(row=0, column=1, sticky="ns")

for i in range(1000):
    textbox.insert(tk.END, "{}\n".format(i))

def scrolling_active(arrow):
    global scrolling
    root.bind('<ButtonRelease-1>', stop_scrolling())
    print(arrow)
    if scrolling == True:
        if arrow == "arrow1":
            textbox.tk.call(textbox._w,'yview', 'scroll', -100, 'units')
        if arrow == "arrow2":
            textbox.tk.call(textbox._w,'yview', 'scroll', 100, 'units')
        root.after(100, lambda a = arrow: scrolling_active(a))

def start_scrolling(event):
    global scrolling
    scrolling = True
    scrolling_active(yscroll.identify(event.x, event.y))

def stop_scrolling():
    global scrolling
    scrolling = False

yscroll.bind("<Button-1>", start_scrolling)

root.mainloop()

Solution

  • There is no event for holding a button down. There are only events for the press and release of a button.

    If you need to track while a button is down, you can set a flag on the press and unset it on a release.

    In your code, you have a bug. Consider this code:

    root.bind('<ButtonRelease-1>', stop_scrolling())
    

    It is functionally identical to this:

    result=stop_scrolling()
    root.bind('<ButtonRelease-1>', None)
    

    To do the binding you must remove the ():

    root.bind('<ButtonRelease-1>', stop_scrolling)
    

    You also need stop_scrolling to accept the event object:

    def stop_scrolling(event):
        global scrolling
        scrolling = False
    

    Also, there's no need to call textbox.tk.call. You can call the yview method on the tkinter object (textbox.yview("scroll", -100, "units")