Python Keyboard Module, wait for user - python

I'm currently building a python code to play Blackjack where I need to be able to call certain functions uppon keypress without necessarily being in the terminal. I found this keyboard module which helped but I came across this issue.
def hit_or_stand(deck,hand):
global playing
print ("\nWould you like to Hit or Stand? Enter 'h' or 's'")
if keyboard.is_pressed('h'):
hit(deck,hand)
if keyboard.is_pressed('s'):
print("Player stands. Dealer is playing.")
playing = False
Let me explain what this function does as I don't want to overload everyone with the entire code. Essentially this function is called in a loop until the player decides to hit s which declares playing as False and therefore stopping the loop. If the player hits h then the hit function is called which draws a card. The player can draw as many cards.
My problem right now is that this code doesn't wait for user keypress. It loops extremely fast repeating it. I only want it to loop after either h or s is pressed.
I tried using keyboard.wait('h') on the line above the first if but then this doesn't allow the user to press s and therefore declare playing as False.
What I'm looking for is something along the lines of keyboard.wait('h'or's') but I know this does not work.
Thank you for your help. I am using python 3.7.9
EDIT: Keyboard Module I am referring too:
https://pypi.org/project/keyboard/

Use keyboard.read_key() to wait for any input.
If it's not h or s ,read_key again.

import keyboard
def mywait():
keyboard.read_key()
def my_function():
print("Hello")
def my_exit():
quit()
keyboard.add_hotkey("p", my_function)
keyboard.add_hotkey("esc", my_exit)
while True:
mywait()

Related

Single key detection to work with the possibility of adding long inputs

I have been facing this problem for the last week,I thought it would be trivial but after trying many different approaches I don't know what else to try.
I have an application where I need to have key detection (to move a robot arm with the keyboard) but when I press enter I need to add some inputs, which should be as long as I want, just some normal input("insert here").
I know about the python libraries to get key detection, I got pynput to work successfully but it crashes my raspberry pi when I start and stop the threads a few times,I tried the Keyboard library but the whole root requirement is a let down, I also got curses to work and this seems to be solid and is (almost) not causing any issues, so detecting 1 key is not a problem.
I of course know how to name my files and get all the information that I need by doing input(), so if I had to use one of those options the job would be rather simple, the challenge comes when I try to apply both approaches together, basically detect the keys to do everything I need, and use python Input to get all the inputs from the user as soon as enter is pressed, all the libraries to detect key seems to take full control and they don't want to release it without a fight. They seem to expect the user to always require single key detection but in my case I would need to constantly turn it on and off, I couldn't figure out any efficient (or not) way to get it to work properly.
My question is:
What is the best approach to have key detection + full user input when needed with curses (or any alternative) in a non blocky way (as my code need to do some other things while listening for keys), is creating and destroying the whole thing the only alternative?
This is my current test code that I created for simplicity (which works but blocks everything while listening for keys):
import curses
import time
import os
stdscr = None
addInput = False
def SetupCurses():
global stdscr
stdscr = curses.initscr()
curses.cbreak()
stdscr.keypad(1)
def StartCurse():
global addInput
key = ''
while key != ord('q'):
key = stdscr.getch()
stdscr.addstr(str(key))
if key == ord('a'):
print("\nyou pressed a\n")
if key == 10:
print("\nyou pressed enter!\n")
addInput = True
break
def EndCurse():
curses.endwin()
while(True):
SetupCurses()
StartCurse()
EndCurse()
if addInput:
theinput = input("add your input\n")
print(theinput)
time.sleep(4)
addInput = False
#if there isn't any input to add I want the code to continue because there is non-related keys stuff to do, but of course it stopped at "StartCurse"
#if there is something to add the code can stop at addInput
The reason for the loop is because the user can save as many positions as he want, so after adding some inputs the possibility of adding more is there.
I saw people making this non-blocking by closing the curses loop after a few seconds (which stops everything anyway...) kind of getting the input by luck...something like:
def ExecuteCurses():
global AddInput
#open it and close it very quickly to grab a key if it is pressed
c = stdscr.getch()
if c == ord('a'):
print("you pressed a")
AddInput = True
time.sleep(1)
curses.endwin()
If you want a full and long user input you will need to use the curses.echo() and then use the stdscr.getstr(). That will wait for the user to press enter().
And to not block the program while getting input you need threading which you will have to import at the top of your program
And for the threading here is a link so you can find out more about threading.
I hope it answers your question

Getting input in python via the same window?

I would like to know how to get user input in python without using the command line or an input box.
Let me explain. I do not want to do this
#All code is python 3
name=input("What is your name?")
Why? When running scripts, the command line is not auto-focused. Furthermore, it pops up another window, something I do not want because I can't hit escape to close it in a hurry (Something which you may want to do if you're playing a game).
What have I tried?
I looked at WX and it's dialog function, something like this:
import wx
app=wx.App()
def text_entry(title,message):
result=None
dlg=wx.TextEntryDialog(None, message,title)
if dlg.ShowModal()==wx.ID_OK: result=dlg.GetValue()
dlg.Destroy()
return result
text_entry("Text entry","Enter something here")
While this works, it pops up another window which again, I do not want. However, it is closer to what I am ultimately looking for, because I can hit escape to make it go away.
I have tried using pygame and it's key.get_pressed() function, but it inserts a lot of the same letter into the entry, even if I gently tap the key. Also, when I implemented it into the project, it can only pick up on normal letters. Writing 26 if statements to detect key presses for a single letter with or without the shift key seems a little counter intuitive.
Finally, I am a bit hesitant to try tkinter. I happen to be blind, and from what I read, tk is very visual, which makes me concerned that it won't play nicely with my screen reader (NVDA).
So, I'm here. After searching on google for "getting input without using command line in python 3", "input in the same window", and "input without using input()" yielded nothing.
To recap, I want to accept user input without using the input() function, and without any additional windows popping up for the duration of me doing so.
Thank you.
What about this solution using the msvcrt module. At any time if you press escape then the program will exit. Python sys.exit(), and built-ins exit() and quit() all call raise SystemExit so this is just one less call to perform. If you press the enter or return key then the while loop ends and you can use the keys that were pressed later in your program as they are stored in the variable user_input. The print at the end just proves that the pressed keys are stored in user_input variable and the input() function simply to leave the window open so you can see it working.
import msvcrt
user_input = b''
while True:
pressed_key = msvcrt.getche() # getch() will not echo key to window if that is what you want
if pressed_key == b'\x1b': # b'\x1b' is escape
raise SystemExit
elif pressed_key == b'\r': # b'\r' is enter or return
break
else:
user_input += pressed_key
print('\n' + user_input.decode('utf-8')) # this just shows you that user_input variable can be used now somewhere else in your code
input() # input just leaves the window open so you can see before it exits you may want to remove
So after doing some more research, I found this:
https://codeload.github.com/Nearoo/pygame-text-input/zip/master
I think this is what I am looking for, though it still needs to be slightly modified. Thank you for the assistance

Code that recognises a keypress in Python 3

Is there anyway for python 3 to recognise a keypress? For example, if the user pressed the up arrow, the program would do one thing whereas if the down arrow was pressed, the program would do something else.
I do not mean the input() function where the user has to press enter after the keypress , I mean where the program recognises the keypress as some as it was pressed.
Is this question too confusing? xD
Python has a keyboard module with many features. You Can Use It In Both Shell and Console.
Install it, perhaps with this command:
pip3 install keyboard
Then use it in code like:
import keyboard #Using module keyboard
while True: #making a loop
try: #used try so that if user pressed other than the given key error will not be shown
if keyboard.is_pressed('up'): #if key 'up' is pressed.You can use right,left,up,down and others
print('You Pressed A Key!')
break #finishing the loop
else:
pass
except:
break #if user pressed other than the given key the loop will break
You can set it to multiple Key Detection:
if keyboard.is_pressed('up') or keyboard.is_pressed('down') or keyboard.is_pressed('left') or keyboard.is_pressed('right'):
#then do this
You Can Also Do Something like:
if keyboard.is_pressed('up') and keyboard.is_pressed('down'):
#then do this
It Also Detect Key For The Whole Windows.
Thanks.
I assume this is a gui program,
If using the built-in gui module Tkinter, you can use bind to connect a function to a keypress.
main.bind('<Up>', userUpkey)
Where userUpKey is a function defined in the current scope.

Issues running a code using Pygame

OKay, so i wrote a code to develop a game using pygame. this is the aim of the game :
there is a player (Mario) which can move only vertically. from the right side of the window, flames appear which the mario has to dodge. the game is very similar to dodger.py !
now, when i run the game, it gets stuck at "Press any key to Enter"
PLEASE HELP !
You are not doing anything in the waitforkey() function.
if event.type == KEYDOWN:
# if key exit blah blah
else:
runGame()
You could put your game in a function called runGame and that would probabaly be the easiest way of doing this. Just remember that the variables will then be local to the scope of that function and any changes won't affect the rest of the program.
Having checked the code on a PC, I have found 3 errors. Two of which are typing errors. First one is on Line 77:
playerrect.topleft = (50,window_hight/2)
Needs to be:
playerrect.topleft = (50,window_height/2)
and the second is on line 126:
WindowSurface.fill(bgcolour)
You haven't defined bgcolour (as far as I could see) so by adding the following to the variables at the top of the file:
bgcolour(255,255,255) #change to what colour you want
The third error I found was in your waitForKey() function. I don't know whether this is important to the running of the program, but you have your if event.type == "QUIT" in speech marks. Like I said, this may not matter but I thought I'd point it out. You have also done this for the other conditions in this function.
By making these changes, you get running code. However, flames do not appear and I don't have time to figure this one out. By fiddling though, I'm sure you'll figure it out!

Python 3.2 Passive User Input

Is there a way to program a function that takes user input without requesting it? For example, during a game of tic-tac-toe, the user could press "Q" at any time and the program would close?
There are a few ways to do this, and they are all different.
If your game is a terminal application using curses, you would catch the q when you call getch(), and then raise SystemExit or simply break out of your while loop that many curses applications use.
Using tkinter or another GUI library, you would bind a key press event to your Frame widget that holds the tic-tac-toe board.
Assuming you are just printing the board out (I have a basic Tic-Tac-Toe game that does that), during input you could close it (even though you specifically asked otherwise):
user_option = input("Enter a space to move to, or 'Q' to quit: ")
try:
if user_option.lower() == 'q': # makes everything lowercase so it is easier to handle
import sys
sys.exit("Game Terminated.")
except TypeError:
# other code
I'm not sure how the player chooses to move, so I used try and except. In my Tic-Tac-Toe game, I have the user input an integer, which corresponds to a space on the board.
Or, you can just have the user press Ctrl+C which is the automatic KeyBoardInterrupt in Python (ends the program).

Categories