desiguel
desiguel

Reputation: 535

How to prevent a function from running on mouse click until previous completes

I'm trying to setup a mouse listener in Python which runs a function on mouse click, as long as that function isn't already running.

from pynput import mouse

def do_work(x, y, button, pressed):
    print(f"Button pressed. Doing work.")
    time.sleep(3)
    print(f"Finished work.")

# Setup mouse listener.
with mouse.Listener(on_click=do_work) as listener:
    listener.join()

So in the above example, even if I smash the mouse button continuously, do_work will only ever run every three seconds.

It feels like I should be able to set this up in a thread but I don't know how to pass the thread into do_work such that it can test if the thread is alive.

Upvotes: 0

Views: 378

Answers (1)

furas
furas

Reputation: 142651

do_work runs sleep which blocks listener for longer time and listener can't get other clicks from system, and it can't skip them - they wait until sleep finish job and then listener gets these clicks from past and runs do_work again and again.

You would have to run do_work in theard. Listener shouldn't runs directly do_work but it should run other function (ie. on_click) and this function should check clicks and start do_work in separated thread or skip clicks.

from pynput import mouse
import time
import threading

# --- functions ---

def do_work(x, y, button, pressed):
    print("Button pressed. Doing work.")
    time.sleep(3)
    print("Finished work.")

def on_click(x, y, button, pressed):
    global job
    
    if pressed:
        if job is None or not job.is_alive():
            job = threading.Thread(target=do_work, args=(x, y, button, pressed))
            job.start()
        #else:
        #    print("skiping this click")
    
# --- main ---

job = None  # default value at start

# Setup mouse listener.
with mouse.Listener(on_click=on_click) as listener:
    # ... other code ...
    listener.join()

Upvotes: 1

Related Questions