Scrolling is not detected - Pynput - python

from pynput.mouse import Listener
from pynput.keyboard import Key, Listener
xy = []
sizes = []
isCtrl = False
size = 11
def on_scroll(x, y, dx, dy):
global size, sizes
global isCtrl
print(isCtrl)
if isCtrl:
size += dy
sizes.append(size)
print(sizes[-1])
def on_press(key):
global isCtrl
if key == Key.ctrl:
isCtrl = True
print(isCtrl)
def on_release(key):
global isCtrl
if key == Key.ctrl:
isCtrl = False
print(isCtrl)
# Collect events until released
with Listener(on_scroll=on_scroll,
on_press=on_press,
on_release=on_release) as listener:
listener.join()
That is the code. I am really not sure why and how my scroll code is working, as the function is not being called even if I scrolled already. Thanks for a solution in advanced!

Some mistakes:
You have imported Listener twice, the keyboard listener covered mouse listener.
Keyboard listener doesn't have on_press method.
Consider that you want to monitor both the mouse and the keyboard.You need to create two threads to listen them.Maybe you need:
from pynput.mouse import Listener as mouseListener
from pynput.keyboard import Key, Listener as keyboardListener
xy = []
sizes = []
isCtrl = False
size = 11
def on_scroll(x, y, dx, dy):
global size, sizes
global isCtrl
print(isCtrl)
if isCtrl:
size += dy
sizes.append(size)
print(sizes[-1])
def on_press(key):
global isCtrl
if key == Key.ctrl:
isCtrl = True
print(isCtrl)
def on_release(key):
global isCtrl
if key == Key.ctrl:
isCtrl = False
print(isCtrl)
# Mouse listener
mouse_listener = mouseListener(on_scroll=on_scroll)
mouse_listener.start()
# Keyboard listener
with keyboardListener(on_press=on_press, on_release=on_release) as listener:
listener.join()

Related

UnboundLocalError: local variable 'toggled' referenced before assignment

I was working on a random python script but I've encountered the above error and cannot figure out how to work it out.
Code:
from pynput.keyboard import Key, Controller, Listener
import time
keyboard = Controller
key = "e"
toggle = Key.f6
toggled = False
def on_press(key):
print(f"on_press() triggered, key = {key}")
if key == toggle:
toggled = not toggled
def on_release(key):
print(f"on_release() triggered, key = {key}")
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
while True:
if toggled:
keyboard.press(key)
time.sleep(3)
keyboard.release(key)
time.sleep(1)

Is there a way to bypass the need to reference self in an argument (Python)

The purpose of my code is to create and print a list of all the keyboard and mouse interactions that occur. The code was working, but then I decided to convert it into a class. From there, I was not able to reference the functions because it considered self to be the first argument.
Here is the code with the class that does not work.
import pyautogui
from pynput.mouse import Listener
MouseListener = Listener
from pynput.keyboard import Listener
KeyboardListener = Listener
from pynput import keyboard
######################
#
# m = move
# p = mouse press
# r = mouse release
# d = scroll down
# u = scroll up
# 1 = key down
# 2 = key up
#
######################
temp = []
class Recorder():
#record mouse movement
def on_move(self, x, y):
temp.append('m{0}'.format(
(x, y)))
#record mouse click
def on_click(self, x, y, button, pressed):
temp.append('{0}{1}'.format(
'p' if pressed else 'r',
(x, y)))
#record mouse scroll
def on_scroll(self, x, y, dx, dy):
temp.append('{0}{1}'.format(
'd' if dy < 0 else 'u',
(x, y)))
#record keyboard press
def on_press(self, key):
try:
temp.append('1({0})'.format(
key.char))
except AttributeError:
temp.append('1({0})'.format(
key))
#record keyboard release and end if esc
def on_release(self, key):
temp.append('2({0})'.format(
key))
if key == keyboard.Key.esc:
# Stop listener
print(temp)
keyboard_listener.stop()
mouse_listener.stop()
return False
mouse_listener = MouseListener(
on_move=Recorder.on_move,
on_click=Recorder.on_click,
on_scroll=Recorder.on_scroll)
keyboard_listener = KeyboardListener(
on_press=Recorder.on_press,
on_release=Recorder.on_release)
keyboard_listener.start()
mouse_listener.start()
keyboard_listener.join()
mouse_listener.join()
And below is the code that performs properly.
import pyautogui
from pynput.mouse import Listener
MouseListener = Listener
from pynput.keyboard import Listener
KeyboardListener = Listener
from pynput import keyboard
##########
#
# m = move
# p = mouse press
# r = mouse release
# d = scroll down
# u = scroll up
# 1 = key down
# 2 = key up
#
##########
temp = []
#mouse recorder
def on_move(x, y):
temp.append('m{0}'.format(
(x, y)))
def on_click(x, y, button, pressed):
temp.append('{0}{1}'.format(
'p' if pressed else 'r',
(x, y)))
def on_scroll(x, y, dx, dy):
temp.append('{0}{1}'.format(
'd' if dy < 0 else 'u',
(x, y)))
#keyboard recorder
def on_press(key):
try:
temp.append('1({0})'.format(
key.char))
except AttributeError:
temp.append('1({0})'.format(
key))
def on_release(key):
temp.append('2({0})'.format(
key))
if key == keyboard.Key.esc:
# Stop listener
print(temp)
keyboard_listener.stop()
mouse_listener.stop()
return False
#activation
mouse_listener = MouseListener(
on_move=on_move,
on_click=on_click,
on_scroll=on_scroll)
keyboard_listener = KeyboardListener(
on_press=on_press,
on_release=on_release)
keyboard_listener.start()
mouse_listener.start()
keyboard_listener.join()
mouse_listener.join()
You can use the decorator #staticmethod for this. Add #staticmethod above the functions in question. For example:
class Recorder:
#record mouse movement
#staticmethod
def on_move(x, y,temp):
temp.append('m{0}'.format((x, y)))
You can now use the function without instantiating an object.
Call the function with:
Recorder.on_move(x,y,temp)
Documentation

Is it possible to press the key without running the if statement again

I'm trying to replace volume media keys with media next-prev keys. The problem is the key volume down or up gets pressed.
from pynput.keyboard import Key, Listener, Controller
keyboard = Controller()
def on_press(key):
if key == Key.media_volume_up:
keyboard.press(Key.media_down)
keyboard.press(Key.media_next)
if key == Key.media_volume_down:
keyboard.press(Key.media_volume_up)
keyboard.press(Key.media_previous)
def on_release(key):
pass
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
I tried to make it like this but it also triggers the previous if statement so it's looping.
from pynput.keyboard import Key, Listener, Controller
keyboard = Controller()
block = False
def on_press(key):
global block
if not block:
if key == Key.media_volume_up:
block = True
keyboard.press(Key.media_volume_down)
keyboard.press(Key.media_next)
block = False
if key == Key.media_volume_down:
block = True
keyboard.press(Key.media_volume_up)
keyboard.press(Key.media_previous)
block = False
def on_release(key):
pass
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()

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

Record (get) mouse click position while key is pressed and stop recording when same key is released in python

I am creating a script where if user press f7 it will start recording mouse clicks and when he releases the button it should stop and this happens unless user closes the program.
The script is printing "None" inspite of pressing f7 and instead of showing click position and "f7", it is showing None.
In on_press function when we print the value, it is showing "f7" but when clicking the mouse button in on_click function, it is showing "None"
Here is the code
from pynput import mouse, keyboard
from pynput.keyboard import Key, Listener
import pickle
x_pos = []
y_pos = []
both_pos = []
pressed_key = None
def on_press(key):
if (key==keyboard.Key.f7):
pressed_key = "f7"
else:
pressed_key = None
def on_release(key):
pass
def on_click(x, y, button, pressed):
if pressed:
#print ("{0} {1}".format(x,y))
print(pressed_key)
if pressed_key == "f7":
x_pos.append("{0}".format(x,y))
y_pos.append("{1}".format(x,y))
#print("test" + x_pos + y_pos)
print (x_pos + y_pos)
#both_pos = x_pos, y_pos
else:
pass
print (x_pos + y_pos)
mouse_listener = mouse.Listener(on_click=on_click)
mouse_listener.start()
with keyboard.Listener(on_press = on_press, on_release = on_release) as listener:
try:
#listener.start()
listener.join()
except MyException as e:
print('Done'.format(e.args[0]))
Found the issue. Because in on_press i was not using global pressed_key so it was creating local variable.
Here is the working code.
from pynput import mouse, keyboard
from pynput.keyboard import Key, Listener
import pickle
x_pos = []
y_pos = []
both_pos = []
pressed_key = None
def on_press(key):
global pressed_key
if (key==keyboard.Key.f7):
pressed_key = "f7"
print(pressed_key)
else:
pressed_key = None
def on_release(key):
global pressed_key
pressed_key = None
def on_click(x, y, button, pressed):
if pressed:
#print ("{0} {1}".format(x,y))
print(pressed_key)
if pressed_key == "f7":
x_pos.append("{0}".format(x,y))
y_pos.append("{1}".format(x,y))
#print("test" + x_pos + y_pos)
print (x_pos + y_pos)
#both_pos = x_pos, y_pos
else:
pass
print (x_pos + y_pos)
mouse_listener = mouse.Listener(on_click=on_click)
mouse_listener.start()
with keyboard.Listener(on_press = on_press, on_release = on_release) as listener:
try:
#listener.start()
listener.join()
except MyException as e:
print('Done'.format(e.args[0]))

Categories