Key Releases Psychopy - psychopy

I'm fairly new to psychopy but I'm having a lot of trouble recording keyboard events so far. The keyboard demo works so I know it is possible, but when I implement the code in my own program it doesn't record any keyboard activity at all. Right now my program is super simple as I'm just trying to get the hang of it. I have a picture and want to record the duration of keypresses during the time the picture is on screen. I have a couple print statements as sanity checks and when I run it (and am using the keyboard) it doesn't print anything. Here's an outline of my code:
from psychopy.iohub import launchHubServer, EventConstants
io = launchHubServer()
keyboard = io.devices.keyboard
keyboard.reporting = True
#-------Start Routine "trial"-------
continueRoutine = True
io.clearEvents('all')
duration_lst=[]
while continueRoutine and routineTimer.getTime() > 0:
# get current time
t = trialClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *image* updates
if t >= 0.0 and image.status == NOT_STARTED:
# keep track of start time/frame for later
image.tStart = t # underestimates by a little under one frame
image.frameNStart = frameN # exact frame index
image.setAutoDraw(True)
if image.status == STARTED and t >= (0.0 + (5.0- win.monitorFramePeriod*0.75)): #most of one frame period left
image.setAutoDraw(False)
# *ISI* period
if t >= 0.0 and ISI.status == NOT_STARTED:
# keep track of start time/frame for later
ISI.tStart = t # underestimates by a little under one frame
ISI.frameNStart = frameN # exact frame index
ISI.start(0.5)
elif ISI.status == STARTED: #one frame should pass before updating params and completing
ISI.complete() #finish the static period
# get keyboard events
for event in keyboard.getEvents():
print event
if event.type == EventConstants.KEYBOARD_CHAR:
key_press_duration=event.duration
duration_lst.append(key_press_duration)
print duration_lst
# check if all components have finished
if not continueRoutine: # a component has requested a forced-end of Routine
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in trialComponents:
if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
continueRoutine = True
break # at least one component has not yet finished
# check for quit (the Esc key)
if endExpNow or event.getKeys(keyList=["escape"]):
core.quit()
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()

I tried stripping off all unnecessary stuff here (variables, window, stimuli etc.) and uses keyboard.getReleases() so it boils down to this:
from psychopy import iohub
io = iohub.launchHubServer()
keyboard = io.devices.keyboard
print 'press something now!'
while True:
# get keyboard releases
for event in keyboard.getReleases():
print 'Released!'
This should print all info about each key release in the console. It works for me, at least. If it also works for you, the problem is probably related to something else in your script.

Related

How do I delay the execution of a function within tkinter button command

I am trying to simulate a computer player "clicking" a button after a human user clicks a button In a grid of buttons. If I use the .after method the 'state' of the button change is delayed but it executes my check_state() method which doesn't detect the change. When I try time.sleep() method it prolongs the human click but still immediately invokes the 'auto' click regardless of where I put it in my code. I want a delay between the human click and 'auto' click.
I have tried widget.after(1000) which gives the desired delay of 'auto' click, but doesn't allow my the change to be seen by my check_state() function. I have tried time.sleep() which delays the execution of the human button click but the 'auto' click is still immediately invokes regardless of which order I place the sleep() function in relation to the call to auto_click(). I know there are better practices for this code implementation like using class based structure which I plan on using once my logic and functionality issues are resolved. My code is as follows:
import tkinter as tk
import random
def app():
def auto_click():
grid_state = get_grid_state()
possible_clicks = []
for i in range(0, len(grid_state)):
if grid_state[i] == " ":
possible_clicks.append(i)
#debug.config(text=possible_moves)
click = random.choice(possible_clicks)
buttons[click].after(1000, lambda: buttons[click].config(text = "auto", state=tk.DISABLED))
#time.sleep(1)
check_grid_state()
check_grid_full()
debug.config(text="test")
def onclick(*arg):
global is_full
buttons[arg[0]].config(text = "clicked", state=tk.DISABLED)
check_grid_state()
check_grid_full()
if not is_full:
auto_click()
def check_grid_full():
global is_full
result=[]
for i in range(len(buttons)):
result.append(buttons[i].cget('state'))
r = [*set(result)]
if r == ['disabled']:
is_full = True
grid_status.config(text=is_full)
else:
is_full = False
Retrieve the current state of the grid
def get_grid_state():
grid_state =[]
for i in range(len(buttons)):
grid_state.append(buttons[i].cget('text'))
return grid_state
Check grid state
def check_grid_state():
grid_states.config(text=get_grid_state())
Global Variables
is_full = False
buttons = []
c=0
Window
root = tk.Tk()
root.title("Title")
Heading
label = tk.Label(root, text="grid state", font = ("Ariel black",22, "bold"))
label.pack()
Grid Frame
frame = tk.Frame(root)
frame.pack()
for row in range(3):
for column in range(3):
buttons.append(tk.Button(frame, text=f" ", font=("arial", "22"), state=tk.ACTIVE, height=2, width=2, command=lambda c=c: onclick(c)))
buttons[c].grid(row=row, column=column)
c += 1
Status bar
grid_states = tk.Label(root, text=f"")
grid_states.pack()
grid_status = tk.Label(root, text=f"")
grid_status.pack()
#btn_is = tk.Label(root, text=f"")
#btn_is.pack()
Debugging output label
debug = tk.Label(root, text="debug")
debug.pack()
Event loop
root.mainloop()
if name == "main":
app()

I am trying to set all rigidbodys' velocity to 0, then to what it was before

So I have been trying to create a pause menu for the past few hours. However, I cannot figure out how to stop the rigidbodies from moving. If there is a way to stop all rigidbodies at once, please tell me, if not, I can set it to each and every script with a rigid body. Here is my code so far:
extends Position3D
onready var charCamera = get_viewport().get_camera()
##var direction = Camera.global_transform.basis.get_euler()
signal spawned(spawn)
export(PackedScene) var spawnling_scene
var linear_velocity_on_pause = 0
var not_paused_anymore = false
var paused = false
#var Popup1 = self.get_parent().get_parent().get_parent().get_node("Popup")
func _physics_process(_delta):
if self.get_parent().get_parent().get_parent().get_node("Popup").visible == false:
if Input.is_action_pressed("leftClick"):
spawn()
if paused == true:
not_paused_anymore = true
paused = false
if self.get_parent().get_parent().get_parent().get_node("Popup").visible == true:
linear_velocity_on_pause = spawnling_scene.instance().linear_velocity
paused = true
spawnling_scene.instance().set_mode(1)
spawnling_scene.instance().linear_velocity = get_parent().get_parent().get_parent().get_node("LinearVelocityOf0").linear_velocity
if not_paused_anymore == true:
spawnling_scene.instance().set_mode(0)
spawnling_scene.instance().linear_velocity = linear_velocity_on_pause
not_paused_anymore = false
func spawn():
var spawnling = spawnling_scene.instance()
spawnling.linear_velocity = charCamera.global_transform.basis.z * -100
#spawnling.global_transform.basis = charCamera.global_transform.basis
add_child(spawnling)
spawnling.set_as_toplevel(true)
emit_signal("spawned", spawnling)
##insert pause system
return spawnling
##var spawnling = spawnling_scene.instance()
##
## add_child(spawnling)
## spawnling.set_as_toplevel(true)
I'm not answering the question of how to set the velocity of all rigid bodies to zero.
If you want to make a pause menu, this is what you should know:
Godot has a puse system, which you can use like this to pause:
get_tree().paused = true
And to resume:
get_tree().paused = false
See Pausing Games.
Which Nodes gets to execute when get_tree().paused is set to true depend on their pause_mode property. By default they will all stop, but if you set their pause_mode to PAUSE_MODE_PROCESS they will continue to work when get_tree().paused is set to true. And that is what you want to do with the Node that make up your pause menu UI.
However, that system will not pause shaders. Their TIME will continue to tick. If you want to "freeze" shaders you can set a 0 to their time scaling like this:
VisualServer.set_shader_time_scale(0)
Set it to 1 for normal speed:
VisualServer.set_shader_time_scale(0)
And you can set other values to have them slow down or speed up.
Speaking of slow down and speed up. If you want to do that for the rest of the game (not just shaders), you can use Engine.time_scale. And if there is some timing that you don't want to be affected, you would have to write it using the time functions in the OS class.

Pysimplegui and Pygame merge

hi I am trying to merge a pygame program with pysimplegui.
i'm looking for a way of grabbing the downstroke of a keyboard key. at the moment i can only see an upstroke of the key no matter what im doing.
I have sucessfully created pysimplegui programs but this is the first time i'm trying to merge with pygame.
window is setup by
window = sg.Window('UNICHALL V2.0',
Win_layout,
border_depth =20,
resizable = True,
keep_on_top = False,
finalize=True,
return_keyboard_events=True,
use_default_focus=False)
and in my pygame program i use
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
stop = pygame.time.get_ticks()
delta = stop - start
key = event.key
if key == 27:
sys.exit(1) ...
i can't get these two work in harmony, they either internally loop forever or simply stop the program dead.
Any help appreciated.
If you just need to detect when key pressed and released, try to bind the event '<KeyPress>' and '<KeyRelease>', not set option return_keyboard_events=True of sg.Window.
Example Code
import PySimpleGUI as sg
layout = [
[sg.InputText('', key='-INPUT-')],
[sg.Button('Add Binding'), sg.Button('Remove Binding')],
]
window = sg.Window('Test Program', layout, finalize=True)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event in ('Press', 'Release'):
e = window.user_bind_event
action = 'pressed' if event == 'Press' else 'released'
print(f'char:{repr(e.char)} | keycode:{e.keycode} | keysym:{e.keysym} | keysym_num:{e.keysym_num} {action}')
elif event == 'Add Binding':
window.bind("<KeyPress>", "Press")
window.bind("<KeyRelease>", "Release")
elif event == 'Remove Binding':
window.TKroot.unbind("<KeyPress>")
window.user_bind_dict.pop("<KeyPress>", None)
window.TKroot.unbind("<KeyRelease>")
window.user_bind_dict.pop("<KeyRelease>", None)
window.close()

macOS Sierra: Emulate Mouse Down and Up

after an update to Sierra I had to find that Karabiner is not working anymore, which could emulate pointer clicks really well.
Any chance to get that via Swift or Apple Script or Obj.C ?
Background: Using Karabiner(and seil) I could bind caps-lock + d down and up to mouse down and up and in between the trackpad movement was understood. My trackpad is not processing keypress anymore but works still fine for pointer moves.
Answering myself, hacked it in hammerspoon. Was quite tricky to get chrome select working, maybe it saves somebody an hour or two:
1 ~/.hammerspoon $ cat init.lua
--[[ Left Keyboard Mouse (alt-d)
The main problem was to get chrome based apps select text when we drag via
keyboard.
You MUST return true always in the handle_drag otherwise it fails to select.
FF works, terminal works, chrome apps (atom, ...) don't.
But true is preventing further processing of the drag coords,
hs.mouse.getAbsolutePosition remains constant while dragging (!)
=> i.e. we MUST calc them via DeltaX, DeltaY, see below.
--]]
hs.alert.show("Config loaded")
-- all mechanics stolen from here:
-- local vimouse = require('vimouse')
-- vimouse('cmd', 'm')
now = hs.timer.secondsSinceEpoch
evt = hs.eventtap
evte = evt.event
evtypes = evte.types
evp=evte.properties
drag_last = now(); drag_intv = 0.01 -- we only synth drags from time to time
mp = {['x']=0, ['y']=0} -- mouse point. coords and last posted event
l = hs.logger.new('keybmouse', 'debug')
dmp = hs.inspect
-- The event tap. Started with the keyboard click:
handled = {evtypes.mouseMoved, evtypes.keyUp }
handle_drag = evt.new(handled, function(e)
if e:getType() == evtypes.keyUp then
handle_drag:stop()
post_evt(2)
return nil -- otherwise the up seems not processed by the OS
end
mp['x'] = mp['x'] + e:getProperty(evp.mouseEventDeltaX)
mp['y'] = mp['y'] + e:getProperty(evp.mouseEventDeltaY)
-- giving the key up a chance:
if now() - drag_last > drag_intv then
-- l.d('pos', mp.x, 'dx', dx)
post_evt(6) -- that sometimes makes dx negative in the log above
drag_last = now()
end
return true -- important
end)
function post_evt(mode)
-- 1: down, 2: up, 6: drag
if mode == 1 or mode == 2 then
local p = hs.mouse.getAbsolutePosition()
mp['x'] = p.x
mp['y'] = p.y
end
local e = evte.newMouseEvent(mode, mp)
if mode == 6 then cs = 0 else cs=1 end
e:setProperty(evte.properties.mouseEventClickState, cs)
e:post()
end
hs.hotkey.bind({"alt"}, "d",
function(event)
post_evt(1)
handle_drag:start()
end
)
and alt I mapped to capslock via karabiner elements.

GtkListBox, how to prevent auto-selecting a row on window show

I have a list box with several rows attached to a window.
list_box = Gtk.ListBox()
list_box.insert(Gtk.Label('foo'), -1)
list_box.insert(Gtk.Label('bar'), -1)
list_box.insert(Gtk.Label('qux'), -1) # ListBoxRow is added automatically
window = Gtk.Window()
window.add(list_box)
window.show_all()
When I call show_all(), the first row of the list is being selected automatically what I don't want to happen. How to prevent auto-selecting it?
I tried changing the order of the functions call
window.show_all()
window.add(list_box)
which broke the layout and the size of the window doesn't fit to the list.
I was running into this issue as well, I used the following code to do it:
listbox = Gtk.ListBox(margin=0)
listbox.set_selection_mode(Gtk.SelectionMode.NONE)
I can still click on each row and do a callback with the following, as well:
listbox.connect("row-activated", self.callback)
The ListBox has a property selection-mode, which you can set to Gtk.SELECTION_NONE. In this case none of the rows will be selected (and cannot be selected later). I don't know if that is what you want.
You can also call the method unselect_all, which will unselect all rows. For this to work, the ListBox must be in SELECT_MULTIPLE or SELECT_SINGLE mode.
This example seems to work completely as expected (i.e. no selection at the start, and if a line is selected, the button can unselect it). If in your installation it doesn't work, I would try to update your packages:
from gi.repository import Gtk
class MainWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.connect("delete-event", self.on_delete)
self.listbox = Gtk.ListBox()
self.listbox.insert(Gtk.Label('foo'), -1)
self.listbox.insert(Gtk.Label('bar'), -1)
self.listbox.insert(Gtk.Label('qux'), -1) # ListBoxRow is added automatically
button = Gtk.Button("Clear selection")
button.connect("clicked", self.on_button_clicked)
vbox = Gtk.VBox()
vbox.pack_start(button, False, True, 0)
vbox.pack_start(self.listbox, False, True, 0)
self.add(vbox)
self.show_all()
Gtk.main()
def on_button_clicked(self, btn):
self.listbox.unselect_all()
def on_delete(self, win, event):
Gtk.main_quit()
def main():
w = MainWindow()
return 0
if __name__ == '__main__':
main()
A note about gtk3 themes: Some themes do not show selected rows at all. Particularly dark themes such as eg. FlatStudioDark, but also some light themes.
Add a dummy label to the top of your list_box and hide it:
dummyLabel = Gtk.Label('nothing') # workaround for focus of title entry
list_box.insert(dummyLabel, -1)
list_box.insert(Gtk.Label('foo'), -1)
list_box.insert(Gtk.Label('bar'), -1)
list_box.insert(Gtk.Label('qux'), -1) # ListBoxRow is added automatically
window = Gtk.Window()
window.add(list_box)
window.show_all()
dummyLabel.hide()
Gtk.main()
The result:
result