Reputation: 7845
I have a paradox here. I'm using GetKeyState in order to retrieve the state of a giving vk_code. I've developed two functions to aid me in my task:
import win32api
def get_key_state(vk_code):
state = int(win32api.GetKeyState(vk_code))
if state == 1 or state == -127:
return 1 # Key is on.
elif state == 0 or state == -128:
return 0 # Key is off.
def press_key(vk_code):
state = int(win32api.GetKeyState(vk_code))
if state == -127 or state == -128:
return 1 # Key was pressed.
else:
return 0 # Key was released.
The value of state
starts with 0, and then while the giving key is held down, it changes to -127, and then when I release, it changes to 1, and then while the key is held down again, it changes to -128, and then finally it gets back to 0.
When I use press_key inside a main loop, like this:
if __name__ == "__main__":
while True:
p_key = 80
if press_key(p_key):
print("P key was pressed.")
I get the following output when the giving key is pressed and released:
How can I get the key press only once if its inside a while loop? Like this:
But without breaking the whole loop.
Observation: I know I'm kinda of reinventing the wheel here (Since I could use PyHook or something), but I really want to know it! I want the "event" to be triggered only once inside the main-loop (Even if the key is kept held down), and I'm failing to grasp the logic to do it.
Upvotes: 2
Views: 1461
Reputation: 1319
Well if you want to ensure that the press will only be registered once no matter how long they hold you can have a state variable to check if this is the first time that particular keypress is registered:
import win32api
HUMAN_KEYPRESS_TIME = 0.3
def press_key(vk_code):
state = int(win32api.GetKeyState(vk_code))
if state == -127 or state == -128:
return 1
else:
return 0
keyDown = False
if __name__ == "__main__":
firstPress = True
while True:
p_key = 80
if press_key(p_key):
if firstPress:
firstPress = False
print("P key was pressed.")
else:
firstPress = True
This won't hold up the loop, and it allows you the press the key as rapidly as your keyboard will allow; the other method only allows you to press every 300 ms and blocks the loop for that long.
Upvotes: 1
Reputation: 7845
Turns out that the solution was pretty obvious. I've solved the problem perfectly using time.sleep().
import win32api
import time
HUMAN_KEYPRESS_TIME = 0.3
def press_key(vk_code):
state = int(win32api.GetKeyState(vk_code))
if state == -127 or state == -128:
return 1 # Key was pressed.
else:
return 0 # Key was released.
if __name__ == "__main__":
while True:
p_key = 80
if press_key(p_key):
print("P key was pressed.")
time.sleep(HUMAN_KEYPRESS_TIME)
I came to the conclusion that it was not possible to "execute only once" while keeping the key held down, and then I realized that the answer was time. If I want the block of code to be executed only once with a single key press, I'd just need to sleep the whole application for the interval of time between each physical key press.
Upvotes: 0