How to monitor the mouse doubleclick in pynput? - python

I am facing a problem when there is a double click during monitoring."can anyone provide me a code that how to monitor mouse doubleclick in python using pynput?"

There is no easy method to get double click when you would like get also single click.
To control double click (without controlling single click) you can remeber time when was previous click and compare with current click. If difference is ie. 0.3s then you can treat it as double click.
Code only for left click
from pynput.mouse import Listener, Button
import time
previous_left = 0
def on_click(x, y, button, pressed):
global previous_left
#text = 'Pressed' if pressed else 'Released'
#print('{0} {1} at {2}'.format(text, button, (x, y)))
double_click_left = False
# double click left button
if pressed and button == Button.left:
current_left = time.time()
diff_left = current_left - previous_left
print('diff left:', diff_left)
if diff_left < 0.3:
print('double click left')
double_click_left = True
previous_left = current_left
# other code
if double_click_left:
# Stop listener
return False
with Listener(on_click=on_click) as listener:
# ... some code ...
listener.join()
Code for other buttons is similar
from pynput.mouse import Listener, Button
import time
previous_left = 0
previous_right = 0
previous_middle = 0
def on_click(x, y, button, pressed):
global previous_left
global previous_right
global previous_middle
#text = 'Pressed' if pressed else 'Released'
#print('{0} {1} at {2}'.format(text, button, (x, y)))
double_click_left = False
double_click_right = False
double_click_middle = False
# double click left button
if pressed and button == Button.left:
current_left = time.time()
diff_left = current_left - previous_left
print('diff left:', diff_left)
if diff_left < 0.3:
print('double click left')
double_click_left = True
previous_left = current_left
# double click right button
if pressed and button == Button.right:
current_right = time.time()
diff_right = current_right - previous_right
print('diff right:', diff_right)
if diff_right < 0.3:
print('double click right')
double_click_right = True
previous_right = current_right
# double click middle button
if pressed and button == Button.middle:
current_middle = time.time()
diff_middle = current_middle - previous_middle
print('diff middle:', diff_middle)
if diff_middle < 0.3:
print('double click middle')
double_click_middle = True
previous_middle = current_middle
# other code
if double_click_left:
# Stop listener
return False
with Listener(on_click=on_click) as listener:
# ... some code ...
listener.join()
But problem is when you want also control single click because it would run some function 0.3s after first click to inform you that it wasn't double click but single click - it would need thread Timer or it would need to run other thread which runs loop wich all time compares curren time with previous_left and if there was no click 0.3s after previous_left then treats it as single click.
I don't have example for this situation.

In addition to the #furas answer, I wanna suggest how to deal with both single and double click events. You just need to create a function that will create threads, and call it from the listener:
import threading
from pynput.mouse import Listener, Button
import time
previous_left = 0
previous_right = 0
previous_middle = 0
def click_handler(x,y,button, pressed):
x = threading.Thread(target=on_click, args=(x,y,button,pressed))
x.start()
def on_click(x, y, button, pressed):
# The code from the comment above to deal with click AND double click
...
with Listener(on_click=click_handler) as listener:
listener.join()

Related

Autoclicker that clicks left click and uses left click as the hot key

This seems really simple but, I realized the issue is that when pyautogui left clicks the key state is reset to up even though I may still be holding down left click.
import win32api
import pyautogui
state_left = win32api.GetKeyState(0x01)
pyautogui.PAUSE = 0.06
stop_key_state = win32api.GetKeyState(0x50)
while True:
a = win32api.GetKeyState(0x01)
b = win32api.GetKeyState(0x50)
if b < 0:
False
if a != state_left: # Button state changed
state_left = a
if a < 0:
while True:
a = win32api.GetKeyState(0x01)
if a < 0:
pyautogui.click()
#print('Left Button Pressed')
else:
False
else:
print('Left Button Released')

Why when I make this function return its value, the function repeats itself infinitely?

This is my code, and in the line, I put a commentary about the return that makes this problem.
from pynput import mouse
def on_move(m_x, m_y):
print('Pointer moved to {0}'.format((m_x, m_y)))
def on_click(m_x, m_y, button, pressed):
#print('{0} at {1}'.format('Pressed' if pressed else 'Released',(m_x, m_y)))
if(pressed):
print("Pressed")
else:
print("( x = "+ str(m_x) + ", y = " + str(m_y) + " )")
return(m_x, m_y) #this is the return
if not pressed:
# Stop listener
return False
def on_scroll(m_x, m_y, dm_x, dm_y):
print('Scrolled {0} at {1}'.format(
'down' if dy < 0 else 'up',
(m_x, m_y)))
# Collect events until released
with mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll) as listener:
listener.join()
# ...or, in a non-blocking fashion:
listener = mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll)
A_coord_x, A_coord_y = mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll)
#listener.start()
print (A_coord_x)
print (A_coord_y)
The only thing I want is that after giving a click the coordinates are saved in the variables A_coord_x and A_coord_y
here is the answer for you. this will release the listener and get you the coordinates in A_coord_x and A_coord_y
from pynput.mouse import Listener
A_coord_x, A_coord_y = 0, 0
def on_click(x, y, button, pressed):
global A_coord_x, A_coord_y
if pressed:
A_coord_x, A_coord_y = x, y
print('{0} at {1}'.format(
'Pressed' if pressed else 'Released',
(x, y)))
return x,y
if not pressed:
# Stop listener
return False
with Listener(on_click=on_click) as listener:
coords = listener.join()
print ('X coordinates :',A_coord_x)
print ('Y coordinates :',A_coord_y)
output:
Pressed at (1211, 400)
X coordinates : 1211
Y coordinates : 400
on_click() is an event handler, you can't return values from it, the return False statement just stops the listener. Just call a set_coordinates(x,y) function from within the handler and you should get your intended result.
Maybe also take a look at the documentation, there is an example on how to work with the mouse.listener

How do I print out from the function?

I try to write some click-event program using pynput library. I can't find out how to print counter out from the function to use it further.
root.counter = 0
def on_click(x, y, button, pressed):
if pressed:
root.counter += 1
logging.info(str(root.counter) + '. Mouse clicked at ({0}, {1}) with {2}'.
format(x, y, button))
print('Button clicked: ' + str(root.counter))
if not pressed:
# Stop listener
return False
listener = mouse.Listener(on_click=on_click)
listener.start()

Convert Hold Left Click to Multiple Left Clicks

I am trying to write a python program that would convert left click being held down to multiple left clicks. Essentially it just spams left click when left click is pressed down. I have written code that does this except that it gets stuck in a loop of because it triggers itself with the left clicks it sends. Here is my code:
from pynput.mouse import Listener
from threading import Thread
import pyautogui
import time
flag = False
def clicking():
while flag:
time.sleep(0.5)
pyautogui.click(button='left')
print("Clicking...")
def clicked(x, y, button, pressed):
global flag
if pressed == True:
if button == button.left:
print("Left Click")
flag = True
thread = Thread(target=clicking)
thread.start()
else:
flag = False
with Listener(on_click=clicked) as listener:
listener.join()
How would I modify this code to stop if from triggering itself and getting stuck in a loop. Thanks!
I use this code as an autoclicker you may be able to do some adjustments to set a listener to a left click.
import time
import threading
from pynput.mouse import Button, Controller
from pynput.keyboard import Listener, KeyCode, Key
def on_press(key):
if key == start_stop_key:
if click_thread.running:
click_thread.stop_clicking()
else:
click_thread.start_clicking()
elif key == exit_key:
click_thread.exit()
listener.stop()
class ClickMouse(threading.Thread):
def __init__(self, delay, button):
super(ClickMouse, self).__init__()
self.delay = delay
self.button = button
self.running = False
self.program_running = True
def start_clicking(self):
self.running = True
def stop_clicking(self):
self.running = False
def exit(self):
self.stop_clicking()
self.program_running = False
def run(self):
while self.program_running:
while self.running:
mouse.click(self.button)
time.sleep(self.delay)
time.sleep(0.1)
start_stop_key = KeyCode(char='+')
#key to start
exit_key = KeyCode(char='ยก')
#key to stop the iteration
button = Button.left
#Either Button.left or Button.right
delay = 0.1
#Time between clicks
click_thread = ClickMouse(delay, button)
mouse = Controller()
click_thread.start()
with Listener(on_press = on_press) as listener:
listener.join()
Good luck

Command to trigger "long click" on left mouse button

I searched in win32gui and PyAutoGUI some commands that make "long - click" on the left mouse button, and I didn't find anything.
I'm actually building a code that helps me to remote another pc's mouse
so i need a command that makes a long click on a mouse.
I put *** on my code so you can see the parts where I need help:
import win32api
import time
state_left = win32api.GetKeyState(0x01) # Left button down = 0 or 1. Button up = -127 or -128
while True:
a = win32api.GetKeyState(0x01)
if a != state_left: # Button state changed
state_left = a
print(a)
if a < 0:
# *** long click on left mouse button ***
print('Left Button Pressed')
else:
# *** stop click on left mouse button ***
print('Left Button Released')
time.sleep(0.001)
In theory, PyAutoGUI covers this with mouseDown & mouseUp functions.
>>> pyautogui.mouseDown(); pyautogui.mouseUp() # does the same thing as a left-button mouse click
>>> pyautogui.mouseDown() # press the left button down
>>> pyautogui.mouseUp(x=100, y=200) # move the mouse to 100, 200, then release the button up.
A solution might be:
pyautogui.dragTo(100, 200, button='left') # drag mouse to X of 100, Y of 200 while holding down left mouse button
pyautogui.dragTo(300, 400, 2, button='left') # drag mouse to X of 300, Y of 400 over 2 seconds while holding down left mouse button
pyautogui.drag(30, 0, 2, button='right') # drag the mouse left 30 pixels over 2 seconds while holding down the right mouse button

Categories