How to use letter/number combinations in pygame, event.key? - pygame

I know that in pygame, for the command:
if event.key==K_r:
That when you press the letter r on the keyboard you get a response. But I would like to increase the complexity to a letter/number combination for a jukebox. So I tried:
if event.key==K_r3:
And I pressed r then I pressed 3. But I get an error: name 'K_r3' is not defined. I'm hoping I don't have to write out a definition for each possible letter/number combination. Any suggestions?

`Don't fret Rico, there is an answer. Try the following:
if event.type == KEYDOWN:
#this says that a key was pressed down
keys = pygame.key.get_pressed()
#this is a list of all the keys that were pressed down. now, if you want to do do multiple keys, the answer is as follows:
if keys[K_3] and keys[K_r]:
(function)
I hope this helps you on your quest to pygame greatness.

Related

Pygame won't read any uppercase keys

As an example, when I try to input (through py.event.get()) the ^ (above the 6), the event reads the shift key, but not the six. The same is true for capital letters and #, #, $, %, *, (, and ). The code below is in a while loop. It works for all the keys that don't require a shift.
for event in py.event.get():
if event.type == py.KEYDOWN:
keys = py.key.get_pressed()
if keys[py.K_CARET]:
print("^")
if event.type == py.K_CARET:
print("^")
See How to get keyboard input in pygame?
pygame.key.get_pressed() returns a list with the state of all keyboard buttons. This is not intended to get the key of a keyboard event. The key that was pressed can be obtained from the key attribute (not type) of the pygame.event.Event object. This also works for uppercase keys:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
print(event.key, event.unicode)
If this doesn't work for you, this is not a general problem, it is related to your system.

Pygame Key Listener for Python 3

I want to be able to control some motors that are hooked up to my raspberry pi through keyboard presses. I have code that turns the motors one direction for 5 seconds and then the other direction for 5 seconds before turning them off. I want to use the key listener function of pygame to control the motors through keyboard presses. I am using the following as a test on the keyboard press aspect.
import pygame
pygame.init()
pygame.key.set_repeat(100, 100)
while 1:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print 'go forward'
if event.key == pygame.K_s:
print 'go backward'
if event.type == pygame.KEYUP:
print 'stop'
When I run this script, I do not get any errors, so I know it runs. However, when I press either the 'w' or 's' key, what displays is either a 'w' or an 's' as if I was just typing. All I want is to be able to execute a function by pressing a key. If there is a different/better way to do it that would be fine.
Pygame KEYDOWN events are looking for key presses in the active window.
You must create a window to tell Pygame where to read events from.
Another solution would be to hook keyboard events from the terminal so you wouldn't have to have a window initialized or in focus, using something like this: Python Key Binding or using the pyHook library to make global keyboard event hooks.
P.S - I realise you solved the problem yourself, I'm including this for completeness.

How to apply keyDown in Sikuli for common key

I need Sikuli to hold a common key f but can't figure out how to do this.
keyDown(Key.F)
keyDown("f")
Doesn't work and tutorials are only about functional keys Ctrs, Shift.
But how to hold a common key?
You can use any key the same way you use functional keys. You can test it by trying the below code while your cursor is located in some text area and you will see that it performs "Select all" (Ctrl+a)
keyDown(Key.CTRL)
keyDown("a")
EDIT
If you want to repeat a key, try something like that:
for i in range(n):
type("a")
where n is the number of times you want to type the letter
The Windows OS, and maybe others, interprets two or three subsequent calls to the same keyDown as holding a key down.
keyDown("f")
keyDown("f")
keyDown("f")
To simulate a SELECT ALL, do this in SikuliX:
type("a", Key.CTRL)
Here is another way (older way):
type("a", KEY_CTRL)
Beware: There is a bug, where, for some computers, the NUM LOCK has to be turned off for the special CTRL commands to work.
Hope this helps!

Tkinter button and entry

I have a couple of defined functions that I want to create buttons for in my GUI. A couple of these functions require one or two arguments(numbers) and that is what's causing problems for me. I have thought about a combination between a button and an entry where when I click the specific button(for one of my functions), an entry will pop up where I type in a number. Then when I press enter I want this number to be used as the argument for the function I have binded to my button and then the function should be executed.
1 function I want to bind to a button:
def move(power, tacho_units):
MOTOR_CONTROL.cmd(5, power, tacho_units, speedreg=0, smoothstart=1, brake=0)
is_ready(5)
We are working with Lego Mindstorms, so Im pretty sure that for example the function above could be a bit confusing for some people.
from Tkinter import *
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="Move", command=!_______!)
self.button.pack(side=LEFT)
root = Tk()
app = App(root)
root.mainloop()
root.destroy()
Does someone have any suggestions/solutions for me? I would appreciate if someone could help me. Do I create a function(that will open a new window with an entry) that I call when I click the Move button? The numbers(power and tacho_units in this function) that I type into the entry is what I want to be used for the function Move when I press enter.
Typically, the way to pass arguments to a function associated with a widget is to use lambda or functools.partial (note: these aren't the only ways). Both of these are somewhat advanced topics, but if you just follow an example, it's fairly safe to use them without fully understanding them.
Here's an example using lambda:
b = tk.Button(..., command=lambda power=1, tacho_units="x": move(power, tacho_units)
While not technically correct, just think of a lambda as a "def" but without a name. It takes arguments and can call functions.
Here is the same thing, using functools.partial:
b = tk.Button(..., command=functools.partial(move, power=1, tacho_units="x"))
Note: you'll have to add an import statement for functools.
functools.partial in essence copies the function (in this case, move) and provides default values for the arguments. Thus, when you call it with no arguments (as tkinter does by default), the parameters will have these default values.
HOWEVER...
Often it's easier to write a function to call your function. The purpose of this extra function is to gather the inputs -- presumably from other widgets -- and then call the final function. For example:
def do_move():
power = power_input.get()
tacho_units = tacho_input.get()
move(power, tacho_units)
b = tk.Button(..., command=do_move)
Whether you use this third method depends on where the argument values come from. If you know the values at the time you create the widget, using lambda or functools.partial works because you can embed the arguments right there. If you're going to be getting the parameters from other widgets, the third form is preferable.
Use lambda function to assign function with arguments
some_power = ... # set value
some_tacho_units = ... # set value
self.button = Button(frame, text="Move", command=lambda a=some_power,b=some_tacho_units:move(a, b) )
or
self.button = Button(frame, text="Move", command=lambda:move(5, 10))

Custom Events in pygame

I'm having trouble getting my custom events to fire. My regular events work fine, but I guess I'm doing something wrong. Here is the relevant code:
evt = pygame.event.Event(gui.INFOEVENT, {'time':time,'freq':freq,'db':db})
print "POSTING", evt
pygame.event.post(evt)
.... Later ....
for event in pygame.event.get():
print "GOT", event
if event.type == pygame.QUIT:
sys.exit()
dispatcher.dispatch(event)
gui.INFOEVENT = 101 by the way. The POSTING print statement fires, but the GOT one never shows my event.
Thanks!
From http://www.pygame.org/docs/ref/event.html
All events have a type identifier. This event type is in between the values of NOEVENT and NUMEVENTS. All user defined events can have the value of USEREVENT or higher. It is recommended make sure your event id's follow this system.
My thought is that your event ID is to high.
It seems to work when I changed the code from:
INFOEVENT = 101
to:
INFOEVENT = pygame.USEREVENT+x
where x is some positive integer.