Despite hunting around I can't seem to find an answer to this seemingly simple question:
I'm new to pygame (but not to python), and am trying to get some code to work from continuous button presses - but get_pressed just does not seem to work for me. I made this just to check that I wasn't going insane (I've left out the importing to make it neat for you guys):
def buttonpress():
while True:
keys = pygame.key.get_pressed()
print keys[K_SPACE]
time.sleep(0.5)
buttonpress()
To the best of my knowledge, this should return a '1' when you press the space bar, but no matter what key you change it too - it simply returns an endless string of zeros.
What am I missing?
Thanks
There is no code that processes the input to get all the keys pressed. In order for this to work you need to call event.poll().
So your code will look like this.
import pygame
from pygame.locals import *
import time
pygame.init()
screen = pygame.display.set_mode((640,380))
def buttonpress():
while True:
keys = pygame.key.get_pressed()
print (keys[K_SPACE])
time.sleep(0.5)
pygame.event.poll()
buttonpress()
One more thing, do not use time.sleep(). This pauses the thread, and can cause the OS to think that your application does not respond (since it's not removing events from the event queue).
Related
import keyboard
import pygame
import mouse
import time
def press_X():
time.sleep(0.2)
keyboard.press('x')
time.sleep(0.6)
keyboard.release('x')
print('Command Executed - press_X')
#SA_R_X V_1.0
#------------------------------------------
while True:
try:
keyboard.add_hotkey('r', press_X)
time.sleep(0.5)
break
except:
keyboard.add_hotkey('r', press_X)
time.sleep(0.5)
break
the problem is the code cannot detect if 'r' is pressed when i am holding 'w' and/or 'space'... (well any key really)
I tried to use a try and except to handle a combination of any key + 'r'. But it did not work. All I need is for the code to be able to detect an 'r' input even if I am pressing/ holding another key at the same time. Then after this the code waits 0.2 seconds before holding down the 'x' key for 0.6 seconds and releasing. Any help is appreciated and it would be very helpful if you included a short explanation on where I went wrong and how you fixed it.
The documentation for this module can be found here. This is where all relevant information can be found.
The best way to do this, from my understanding, is to use an alternative function. If you want the program to continue to run, even though the key has not been pressed, then I suggest using the keyboard.on_press_key() function. This would mean that the rest of your program could still run, and your press_X() function could be run as a callback. Here is an example of how this code could be implemented.
import keyboard
import pygame
import mouse
import time
class App:
running = True
def press_X():
time.sleep(0.2)
keyboard.press('x')
time.sleep(0.6)
keyboard.release('x')
print('Command Executed - press_X')
App.running = False
#SA_R_X V_1.0
#------------------------------------------
keyboard.on_press_key('r', lambda x: press_X()) ## Adds an event listener for the r key
## This will stop execution if there is no code after this point
If you want it to stop the program and wait for the r key to be pressed, then you could use keyboard.wait(). This will basically pause your program until the key is pressed, after which your function would be run. For example, to replace the keyboard.on_press_key('r', lambda x: press_X()):
keyboard.wait('r')
press_X()
From my understanding, keyboard.add_hotkey() does not work in your situation because it is looking for an exact combination of keys being pressed, such as Ctrl+C, and will only go if only the keys in the hotkey are pressed.
I hope this helps, good luck!
I wanted to make a simple macro to hold down 'W' for some time, but even simple script like this does not work.
import time
import pyautogui
from pynput.keyboard import Key, Controller
keyboard = Controller()
pyautogui.keyDown('w')
time.sleep(3)
pyautogui.keyUp('w')
time.sleep(5)
keyboard.press('w')
time.sleep(3)
keyboard.release('w')
If i test it in any text editor/text input window it will write one 'w' when script starts and anouther one after 8 seconds without holding/spaming it. And therefore it DOES NOT work in any games what should be the whole purpose of this script. I tried it in a huge variety of different games (Java Minecraft, source Gmod, Roblox and some unity games) and this script just was not working in any of them, but if a game has chat, search box or any other text input window, this script will write one 'w' and anouther one after some time in it.
I realy have no idea why this is happening, but i remembered that two years ago i tried to make similar script on pynput and it did work, so i tried installing old versions of pynput, but that did not help me as well...
So after a long time i could finaly take care of the issue, and i figured out that the source of the problem was in the Microsoft's DirectInput. Basically pynput and pyAutoGUI are not able to get in to DirectInput and there is no signal at all while I thought that there wwas a signal, but for so little amount of time that the games just were not able to pick it up. And the solution to this was pretty easy thanks to this guy PyAutoGUI not working? Use DirectInput. Thanks to his PyDirectInput librarry you are able to use python to emulate button presses and holdes in games!
This might be a start to work with:
#https://stackoverflow.com/questions/66284097/pynput-and-pyautogui-cant-hold-keys
#simulate keystroke for some amount of time
import msvcrt
import time
def press(char, duration, sleep, limit=None):
while True:
lim = limit
t1 = time.time()
while time.time() - t1 < duration: # do for duration specified
msvcrt.putch(char) # output character, putch() awaits a byte string
if lim: # limit specified?
lim -= 1
if lim == 0: # limit reached
break
time.sleep(SLEEP)
if msvcrt.kbhit(): # key pressed?
char = msvcrt.getch()
press(b'w', .001, 2, None)
I was making a bot that would basically keep the left mouse button clicked or unclicked based on a toggle. I get it to work but then it started lagging my entire computer so I didn't take it one step further, being scared to burn my PC, how It happened to my phone one year ago. So we are finally here asking you guys for some optimization to my project.
Code:
import keyboard
import win32api, win32con
from pynput.mouse import Button, Controller
mouse = Controller()
play=False
def toggle():
global play
if play==False:
play=True
else:
play=False
keyboard.add_hotkey('home',toggle)
played=False
while True:
if play==True and played==False:
played=True
mouse.press(Button.left)
elif play==False:
mouse.release(Button.left)
played=False
else:
pass
You should put a time.sleep() or something to wait between each loop because your while statement is running again and again without any pauses.
You can slow the while loop by inserting a sleep function in it. To do this, import the module time and call the function time.sleep(ms) in your while loop. It will be less reactive but you can set a sleep time of only a few ms and it will be better because the program will not be running at full speed all the time.
This is the programme I wrote but I'm not sure what's wrong:-
import turtle
import random
bob = turtle.Turtle()
screen = turtle.Screen()
def coord(x,y):
print(x,y)
turtle.onscreenclick(None)
turtle.onscreenclick(coord)
turtle.listen()
print('hello')
turtle.done()
The programme works fine except that the print('hello') part happens first, followed by the on screen event. How do I make the onscreen event occur first before the rest of my programme?
You can simply make the rest of your code part of the coord function:
def coord():
print(x,y)
turtle.onscreenclick(None)
print("Hello")
# The rest of your program goes here.
However, a few things to note:
This isn't an amazing elegant solution, especially if you intend to set up other events further into your code. It can become quite hard to keep track of.
It's imperative that you remove the event binding (in this case the binding of coord to onscreenclick) as soon as it's been used, otherwise you could end up with multiple instances of the same code running at once if someone double-clicked the screen, for example. In your case you've already done this (with turtle.onscreenclick(None)), but it is something to keep in mind.
If you choose to go this route, don't forget to rename the coord function something more representative of what that section of your code will do.
I have a Raspberry pi with a Sense hat. I've made a binary clock that I want to display and keep updated on the Sense hat's display. However, I want the ability to toggle the clock on and off with joystick middle. Everything's working fine, apart from my clock's update-loop blocking any new input once it's started.
from sense_hat import SenseHat
from signal import pause
def show_clock():
# clock-logic
def pushed_middle(event):
while 1:
show_clock()
sense = SenseHat()
sense.stick.direction_middle = pushed_middle
pause
I've been thinking about how to solve this. How to allow the script/clock to keep running and still accept new actions from the joystick. But once the while-loop starts, I'm stuck. I'm not sure what to google for. I've started looking into async/await, but that seem to be a Python 3.5+ feature, and my pi only has 2.7.9/3.4.2(I just sudo apt-get update/upgrade-ed). I've also tried moving the loop around in the program, but it's blocking everything no matter where I place it.
Is it a non-blocking (infinite) loop I'm looking for?
Is this what a game-/event-loop is?
Can I solve this with out using multiple threads(just curious, not a limitation if it's a must)?
Is this a general problem in "designing" infinite loops?
Can I approach this as a (reverse?) race condition? I was thinking about maybe using a semaphore as some kind of tool to not block, but I'm not sure.
I solved it by using a global variable:
from sense_hat import SenseHat
from signal import pause
def show_clock():
global clock_is_on
while clock_is_on: # clock-loop
# clock-logic
# ...
events = sense.stick.get_events()
for event in events:
if event.direction == "middle" and event.action == "pressed":
clock_is_on = False
time.sleep(1) # only need to update clock once every second
def pushed_middle(event):
if not clock_is_on:
clock_is_on = True
show_clock()
sense = SenseHat()
clock_is_on = False
sense.stick.direction_middle = pushed_middle
pause()