I’m writing this input text box with psychopy, basically redrawing the screen every time when there is a keypress. The problem is that right now people are unable to type in capital letters or to type a question mark, both of which requires being able to detect if “shift” is being pressed at the moment. How can I do that?
class InputTextBox(object):
def __init__(self, window, pos=(0, -0.5), size=(1.4, 0.8), character_limit=None, valid_characters='[a-zA-Z0-9]',
resp_type=None, validation_func=lambda x: True, illegal_input_err_message='illegal input!'):
self.window = window
self.text_buffer = ''
self.box_params = {'win': window,
'name': 'box',
'fillColor': 'white',
'pos': pos,
'width': size[0],
'height': size[1]}
self.text_params = {'win': window,
'name': 'text',
'font': u'Arial',
'alignHoriz': 'left',
'alignVert': 'top',
'pos': (pos[0] - size[0] / 2 + 0.01, pos[1] + size[1] / 2 - 0.01),
'height': 0.05,
'color': 'black',
'wrapWidth': size[0] - 0.02}
self.box = Rect(**self.box_params)
self.text_box = TextStim(text='|', **self.text_params)
self.character_limit = character_limit
self.valid_characters = valid_characters
self.illegal_input_err_message = illegal_input_err_message
self.resp_type = resp_type
self.validation_func = validation_func
if resp_type == 'num' and validation_func is None:
self.validation_func = isnumber
elif resp_type == 'int' and validation_func is None:
self.validation_func = isinteger
def set_auto_draw(self, auto_draw=True):
self.box.setAutoDraw(auto_draw)
self.text_box.setAutoDraw(auto_draw)
def get_input_result(self):
if self.resp_type == 'num':
return float(self.text_buffer)
elif self.resp_type == 'int':
return int(self.text_buffer)
return self.text_buffer
def update_text(self, key):
special_char_list = {'space': ' ',
'period': '.',
'comma': ',',
'apostrophe': '\'',
'backslash': '\\',
'minus': '-',
'equal': '=',
'slash': '/'}
if key == 'backspace':
self.text_buffer = self.text_buffer[:-1]
key = ''
elif key in special_char_list:
key = special_char_list[key]
elif not re.match(''.join(['^', self.valid_characters, '$']), key):
key = ''
if self.character_limit and type(self.character_limit) is int:
if len(self.text_buffer) >= self.character_limit:
key = ''
self.text_buffer = self.text_buffer + key
self.text_box.setText(text=self.text_buffer + '|')
def get_input(self, time_limit=None, exit_key='return'):
self.box.draw()
self.text_box.draw()
self.window.flip()
event.clearEvents(eventType='keyboard')
timer = core.Clock()
while True:
keyboard_input = event.getKeys()
for key in keyboard_input:
self.update_text(key)
if exit_key in keyboard_input:
if not self.validation_func(self.text_buffer):
self.text_box.setText(self.illegal_input_err_message)
self.box.draw()
self.text_box.draw()
self.window.flip()
time.sleep(1)
self.update_text('')
else:
break
elif time_limit and timer.getTime() > time_limit:
break
elif 'escape' in keyboard_input:
core.quit()
self.box.draw()
self.text_box.draw()
self.window.flip()
return self.get_input_result()