import pynput
import time
def poschange(x,y):
#print(f"{x},{y}")
print("poschange called")
pynput.mouse.Controller().position = (0,0)
def stop(key):
#print(key)
try:
if key.char == 'a':
print("stopped")
keyli.stop()
mouli.stop()
exit()
except:
pass
keyli = pynput.keyboard.Listener(on_press = stop)
keyli.start()
mouli = pynput.mouse.Listener(on_move = poschange)
mouli.start()
keyli.join()
mouli.join()
I just want to lock the mouse position when of the the mouse to (0,0) until I press the 'a' key on the keyboard and then the program terminates and i get control my mouse again.
To my knowledge in this code when ever i move the mouse the poschange() method is called and the mouse position must be set back to (0,0) and repeat again until the mouse listener thread is terminated, but it just works twice, the print statement in the poschange() function is printed twice in the console and then the mouse becomes sluggish and moves slowly, when I press 'a' the listeners must stop and program must terminate but it doesn't I have to manually do it and only the the mouse becomes fast and normal again. But when I remove the line pynput.mouse.Controller().position = (0,0) from the code the thing works as i intend, it prints the print statement "poschange called" every time I move the mouse and the program terminates as expected when I press the 'a' key.
can someone please tell me why and tell me whats wrong with this. Thanks in advance.
You've created a recursion with that call to .position as you move the cursor position in a callback triggered when a cursor changes its position.
I suppose you may get expected behavior by calling that
pynput.mouse.Controller().position = (0,0)
upon application start and by preventing the event propagation with:
mouli = pynput.mouse.Listener(on_move=poschange, suppress=True)
Related
I'm trying to make a program that randomly moves the mouse only when the right mouse button is held to prank a friend.
I found some code online to detect right-clicks with Win32 API. When I added my own while loop, it didn't stop after it started. I tried adding an if statement with break but nothing changed.
import win32api
import pyautogui
import random
state = win32api.GetKeyState(0x02) # Right button down = 1. Button up = -128
while True:
pressed = win32api.GetKeyState(0x02)
if pressed != state: # Button state changed
state = pressed
print(pressed)
if pressed < 0:
print('Right Button Pressed')
while pressed < 0: # If the right mouse button is pressed, move the mouse randomly.
pyautogui.moveRel(random.randint(-10, 10), random.randint(-10, 10))
if (pressed > 0):
break
else:
print('Right Button Released')
You can try replacing your main while loop with this one that uses the assignment (walrus) operator := to continuously check the button state
has_right_clicked = False # flag if the button has been pressed yet
while state := win32api.GetKeyState(0x02) # Right button down = 1. Button up = -128:
if state == 1: # If the right mouse button is pressed, move the mouse randomly.
has_right_clicked = True # user has right-clicked, set the flag
pyautogui.moveRel(random.randint(-10, 10), random.randint(-10, 10))
if has_right_clicked: # this will be ignored until the flag is set
break # if the user lets go of the button
The loop will start automatically because both 1 and 128 evaluate to True, which is why we need the extra has_right_clicked flag to break the loop! The caveat here, however, is that this loop will only run once. You should probably wrap this in a function that's bound to right-click so it can be called whenever the user right-clicks the mouse.
Waiting for input with GetKeyState is never the correct solution for anything.
To capture global mouse events you should probably use a low-level mouse hook in this case. I don't know if it is possible in Python but I assume there is a way...
I tried making a simple autoclicker but it is not working for me.My cursor is moving slowly as f***.
You guys have an idea how to fix this?
Problem: line 11, pyautogui.click(button='left') is not clicking.
from pynput.mouse import Listener, Button, Controller
import pyautogui
# This function will be called when any key of mouse is pressed
def on_click(*args):
# see what argument is passed.
print(args)
if args[-1]:
# Do something when the mouse key is pressed.
print('The "{}" mouse key has held down'.format(args[-2].name))
pyautogui.click(button='left') # <--- lagging mouse
elif not args[-1]:
# Do something when the mouse key is released.
print('The "{}" mouse key is released'.format(args[-2].name))
# Open Listener for mouse key presses
with Listener(on_click=on_click) as listener:
# Listen to the mouse key presses
listener.join()
Supposing this is on a while or for loop, you can make it faster by changing the pyautogui.pause variable. Write this on top of your code:
pyautogui.PAUSE = .001
It specifies the delay between each pyautogui function call.
On my Windows 10 Computer running the topic poster code from question led to Python window that doesn't close for an hour and I can't close it with Task Manager.
So be careful with executing this code.
I'm pretty new to Python and I'd like to make a kind of an Autoclicker, which keeps clicking every 0.1 seconds when my left mouse button is held down.
My Problem is, that when I run my script, my mouse instantly starts clicking. What should I do?:
import win32api
import time
from pynput.mouse import Button, Controller
mouse = Controller()
while True:
if win32api.GetAsyncKeyState(0x01):
mouse.click(Button.left, 1)
time.sleep(0.1)
else:
pass
Thanks
My Problem is, that when I run my script, my mouse instantly starts clicking. What should I do?
If the function succeeds, the return value specifies whether the key
was pressed since the last call to GetAsyncKeyState, and whether the
key is currently up or down. If the most significant bit is set, the
key is down, and if the least significant bit is set, the key was
pressed after the previous call to GetAsyncKeyState.
You should use win32api.GetAsyncKeyState(0x01)&0x8000 instead.
Now, the only thing it does is click once, which makes my click a double click.
Because GetAsyncKeyState detects the key state of the left mouse button. When you press the left mouse button, the click function is called, click will realize the two actions of the left mouse button press and release. Then in the place of the while loop, GetAsyncKeyState will detect the release action, which is why it stops after double-clicking.
I suggest you set the left mouse button to start and the right mouse button to stop.
Code Sample:
import win32api
import time
from pynput.mouse import Button, Controller
mouse = Controller()
while True:
if (win32api.GetAsyncKeyState(0x01)&0x8000 > 0):
flag = True
while flag == True:
mouse.click(Button.left, 1)
time.sleep(0.1)
if (win32api.GetAsyncKeyState(0x02)&0x8000 > 0):
flag = False
else:
pass
Check if win32api.GetAsyncKeyState(0x01) < 0 in the if condition.
I made it work with mouse5!
import win32api
import win32con
import time
from pynput.mouse import Button, Controller
mouse = Controller()
def ac():
if keystate < 0:
mouse.click(Button.left, 1)
time.sleep(0.1)
else:
pass
while True:
keystate = win32api.GetAsyncKeyState(0x06)
ac()
I have this relatively simple program that listens for mouse clicks and when the mouse button is held down prints "1"s. Unfortunately when I let go of the mouse it just keeps printing "1"s, even though there is an if statement which checks if the mouse is clicked and should stop the loop if it is not. I am using the pynput.mouse module for the mouse interaction.
Here is my code:
import time
from pynput.mouse import Listener
def clicked(x, y, button, pressed):
if pressed == True:
while button == button.left:
print("1")
time.sleep(1)
if pressed == False:
break
with Listener(on_click=clicked) as listener:
listener.join()
My theory is that once the loops starts it stops listening for mouse clicks, so it can never stop the loop. Would it be necessary to create a new thread for the loop? If yes, how would I do that?
Thanks!
Your current logic makes it impossible to get out of the loop, since pressed doesn't change within the loop. There is not a statement that checks if the mouse is clicked: your only if statements check whether the mouse was clicked when you entered the function. pressed doesn't change within the function.
Look at the critical logiic:
if pressed == True:
while ...
...
if pressed == False:
break
There is nothing in here to change the value of pressed; the first if guarantees that it's True anywhere within the loop.
Yes, you need to set up another listener that operates within the loop. You already know the building blocks: create a new one within the function and bind it to another operation that breaks the loop. For instance, you might "cheat" and have it reset pressed as a global variable.
You could also research how to do this in other answers, if you want an overall handler solution. keypress and keyrelease have been done often enough.
import pyautogui, random, time
import pynput
keys = ['w', 's', 'a', 'd']
def on_press(key):
p = True
if key == pynput.keyboard.Key.esc:
return False
else:
while p == True:
press = keys[random.randint(0,3)]
pyautogui.keyDown(press)
pyautogui.keyUp(press)
p = False
with pynput.keyboard.Listener(on_press=on_press) as L:
L.join()
a code like this will work instead of what you did.
BTW, that is just an example; feel free to visit my GitHub page: github.com/ironnicko
I a pretty new to panda3d, and I came across a problem that I have no idea how to fix. I am trying to control the camera using the cursor's location, but every time it the cursor leaves the application window, and reenters it the program stops recording the cursor's position. Is this a task problem? I put the function's that receive the cursor position and control the camera into taskmgr. That section of my code is below.
taskMgr.add(self.get_mousepos, 'getmouse')
taskMgr.add(self.move_camera, 'movecam')
def get_mousepos(self,task):
if base.mouseWatcherNode.hasMouse():
self.camerax=base.mouseWatcherNode.getMouseX()
self.cameray=base.mouseWatcherNode.getMouseY()
return Task.cont
def move_camera(self,task):
if self.camerax>=.6:
self.camh-=.8
camera.setHpr(self.camh,self.camh1 ,0)
elif self.camerax<=-.6:
self.camh+=.8
camera.setHpr(self.camh,self.camh1 ,0)
elif self.cameray>=.6:
self.camh1+=.8
camera.setHpr(self.camh,self.camh1 ,0)
elif self.cameray<=-.6:
self.camh1-=.8
camera.setHpr(self.camh,self.camh1 ,0)
return Task.cont
Thanks in advance.
You should remove one indent in front of return Task.cont. Otherwise, the task will only continue as long as the mouse cursor is in the window; as soon as it leaves the window, hasMouse() will return False and the task will stop running.