(Python) Detecting arrow key(press) on Windows - python

I tried to search for my answer before I posted, but I wasn't able to find anything that could help me here.
I currently have this in my script:
def waitForDir(self):
while True:
if msvcrt.kbhit():
keyHit = msvcrt.getch()
print keyHit
(It's part of a larger class)
Whenever I press the arrow keys, I get a pretty weird-looking symbol that kinda reminds me of a fish (think of an infinity symbol with the right half of the second loop cut off) and a letter -- K for left, H for up, M for right, P for down. (I'm using the arrow keys typically between the numpad and the main keyboard, below the home/insert/delete/all that jazz keys)
...how can I get this to something I can use? I want to run events whenever one of the keys is pressed, but I really don't know how to do it.
I can provide more info if I need to. Thanks in advance!
EDIT: Nevermind! I figured out the solution by enclosing msvcrt.getch() with ord() to get usable numbers. Thanks anyway!

Related

How to hold an keyboard key using pynput/pyautogui [duplicate]

I'm currently working on a script that presses the 'w,a,s,d' keys in order to move a character in any game.
For this to work, i need to have the 'w' key pressed for a specific amount of time. How can I achieve this?
I thought of something like:
pyautogui.keyDown('w')
time.sleep(2)
pyautogui.keyUp('w')
But this just pauses the whole program and no key is being pressed so this has no use to me.
As said in the doc-string from pyautogui.keyDown():
Performs a keyboard key press without the release. This will put that
key in a held down state.
NOTE: For some reason, this does not seem to cause key repeats like would
happen if a keyboard key was held down on a text field.
You need a different approach - you can may use pygame - with this
Or, if you want to stay with pyautogui you can try something like this:
def hold_W (hold_time):
import time, pyautogui
start = time.time()
while time.time() - start < hold_time:
pyautogui.press('w')
with pyautogui.hold(key):
pyautogui.sleep(hold)
This will do the trick without making your own function.

Left click detection with ursina

I'm using ursina to make a game, and I want to detect a left click so that I can shoot. So, here's my code :
def update(self):
if held_keys['t']:
print("it works !")
Whenever I press 't', it prints 'it works !', and if I hold it, as long as it's held, the message is printed. Great ! But now, if I try with 'left mouse down' for my key, it doesn't work anymore !
My code would then be :
def update(self):
if held_keys['left mouse down']:
print("it works !")
So, the problem here is clearly the 'left mouse down' argument. But I'm sure it is the correct syntax :
according to the documentation (https://www.ursinaengine.org/cheat_sheet.html#Keys)
and according to another test I made with it, where it worked (in another situation)
So, the syntax of my argument is correct, my code is correct. Where is the error located then ? Is there a specific way to handle the mouse, different than the keyboard ? I really don't think so, that's why I'm kinda confused here.
The way to debug this would be to print the held_keys dict to see what it contains. The correct name is 'left mouse'. It is that way because the mouse button names are named differently than other keys and are mostly there to make code changes easier. Mouse buttons aren't keys after all.
However, what you could do is check mouse.left instead.

Hashtag character not displaying correctly

The following fails to print a hashtag?
import pyautogui
pyautogui.typewrite('#');
It prints '~'.
Pyautogui is keyboard layout dependent.
You could try switching your keyboard layout to the US keyboard layout (which is what Pyautogui is based on). For example, the French Canadian keyboard layout has a # where the ~ key normally is, which could explain why you're experiencing this behavior.
As Sean Kennedy said, it's a keyboard layout issue. They're still working on support for non-US-English keyboard layouts.
https://github.com/asweigart/pyautogui/issues/137
Luckily you have an English keyboard layout, so you'll have far fewer issues and you should be able to patch them. You can redefine whether certain keys need shift or not by editing _pyautogui_win.py:
def _keyDown(key):
if key not in keyboardMapping or keyboardMapping[key] is None: return
needsShift = pyautogui.isShiftCharacter(key)
# insert this code, exactly here:
if key == '#': needsShift = False
if key == '+': needsShift = False
if key == '<': needsShift = False
#print(key,needsShift) #####debug
# continue
Taken from:
https://github.com/asweigart/pyautogui/issues/46#issuecomment-132640299
I haven't looked at the code myself, but you might find that you're better or worse making the edit inside isShiftCharacter.
I should have kept reading. isShiftCharacter might become a rabbit hole:
By the way: Deleting #,+,< in the following function, did NOT work
(util.py in .\pyautogui):
def isShiftCharacter(character): return character.isupper() or
character in '~!##$%^&*()_+{}|:"<>?'
Maybe .isupper() regards these characters as upper? I didn't check
further
I think this can be an alternative if pyautogui doesn't work for #,etc
import keyboard
keyboard.write('#')

PyAutoGui - Press key for X seconds

I'm currently working on a script that presses the 'w,a,s,d' keys in order to move a character in any game.
For this to work, i need to have the 'w' key pressed for a specific amount of time. How can I achieve this?
I thought of something like:
pyautogui.keyDown('w')
time.sleep(2)
pyautogui.keyUp('w')
But this just pauses the whole program and no key is being pressed so this has no use to me.
As said in the doc-string from pyautogui.keyDown():
Performs a keyboard key press without the release. This will put that
key in a held down state.
NOTE: For some reason, this does not seem to cause key repeats like would
happen if a keyboard key was held down on a text field.
You need a different approach - you can may use pygame - with this
Or, if you want to stay with pyautogui you can try something like this:
def hold_W (hold_time):
import time, pyautogui
start = time.time()
while time.time() - start < hold_time:
pyautogui.press('w')
with pyautogui.hold(key):
pyautogui.sleep(hold)
This will do the trick without making your own function.

Python - Curses - Addstr -multicolored string/understanding functions

I don't know what the right words are to ask my question, so please excuse the extra detail below. I am as much asking for the right words/concepts as for an answer to the specific question.
I'm trying to put a simple console in front of a script of mine using curses in Python. I want the console to look relatively familiar and have key shortcuts for 3 commands (Load, Exit, Continue). To highlight which key is the hotkey for an action, I wanted that letter to be in a different colour. (e.g. Exit with hotkey being the x). I figure this must be made up of 3 "addstr" commands- write the first letter in normal ("E"), then the x with a colour attribute, then "it" in normal colour again.
I thought that because I do this 3 times, and maybe more in future screens, I should make a function to do it for me to see if that works. What I can't figure out though, is how to edit the screen without hardcoding the function to the variable name. I want to be able to call the function in a number of different windows. I thought at first I could just pass the screen's variable into my function but that doesn't seem right.
Here is my pseudo code I started working on:
def keyString(menuString,fastChar,highlight,startX,startY,cScreen):
#menuString is the word that has a letter to bring to attention
#fastChar is the character that will be in a different colour
#highlight is binary value to determine which colour pair to use
#definition expects 'h' and 'n' to be colour pairs
#startX and startY are the beginning cursor positions
#cScreen would be global screen variable
fCidx = menuString.find(fastChar) #index of the character to highlight
fXadj = startX + fCidx #set the x position for character to highlight
sHx = fXadj + 1 #set the x position for the remainder of the string
fH = menuString[0:fCidx] #Slice the first half of the string
sH = menuString[(fCidx+1):] #slice the remainder of the string
if highlight:
txtColor = h
else:
txtColor = n
cScreen.addstr(startY,startX,fH,txtColor)
cScreen.addstr(startY,fXadj,fastChar)
cScreen.addstr(startY,sHx,sH,txtColor)
return cScreen
Please ignore the awful variable names..I was getting tired of typing and started shorthanding. I realise that I didn't need to worry about explicitly stating x,y coords because the cursor position is remembered. So a lot of that can be cut out. I'm not asking for someone to fix my function. I just don't have a concept of how to have a function that will write out a word using different colours for different characters. I could probably stick a "global screen" in the function and only use it for editing "screen", but then (for example) I wouldn't be able to use the function for "screen2".
If it helps anyone searching in the future, I found that I can use Windows (curses.newwin) and those can be fed into, and returned from functions.
So for example, if the above code was in a file called "curse_tools.py":
import curses
import curse_tools
def Main(screen):
curses.init_pair(1,curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(2,curses.COLOR_BLACK, curses.COLOR_GREEN)
n = curses.color_pair(1)
h = curses.color_pair(2)
curse_tools.n = n
curse_tools.h = h
try:
screen.border(0)
box1 = curses.newwin(20, 20, 5, 5)
box1.box()
box1=curse_tools.keyString("Exit","x",False,1,1,box1)
screen.refresh()
box1.refresh()
screen.getch()
finally:
curses.endwin()
curses.wrapper(Main)
This code would work. I'm going to re-write my original code because I learned a lot along the way but maybe a future beginner will somehow come across this question so I thought I'd post the 'solution'. Although I still don't know the right words.
Most of the code in this post came from Why won't my curses box draw? (in case it looks familiar)

Categories