Reputation: 185
I want an experiment that displays a bunch of random dots, then asks the user to input the correct number of dots they saw. I want the experiment to loop. I can get this to work for 1 iteration, but something is wrong with the looping because the window and the dialogue are colliding, or the window isn't properly closing. When running this script Psychopy currently, the gui freezes. I've tried both python3 and python2 with my code.
import random
import psychopy.visual
import psychopy.event
import psychopy.core
from psychopy import gui
import time
while True:
win = psychopy.visual.Window(
size=[500, 500],
units="pix",
fullscr=False
)
myDlg = gui.Dlg(title="Response")
n_dots = random.randint(5, 200)
dot_xys = []
for dot in range(n_dots):
dot_x = random.uniform(-250, 250)
dot_y = random.uniform(-250, 250)
dot_xys.append([dot_x, dot_y])
dot_stim = psychopy.visual.ElementArrayStim(
win=win,
units="pix",
nElements=n_dots,
elementTex=None,
elementMask="circle",
xys=dot_xys,
sizes=10,
contrs=random.random(),
)
dot_stim.draw()
win.flip()
psychopy.event.clearEvents()
time.sleep(4)
win.close()
myDlg.addField('How many dots did you see?')
number = myDlg.show()
if myDlg.OK:
print(number)
myDlg.close()
psychopy.core.quit()
I'm using the latest version of Psychopy. Please let me know if you have any suggestions. Thanks!
Upvotes: 0
Views: 377
Reputation: 5683
Generally, you would not use a dialogue box to collect responses. Rather, you'd make something that works inside the window using psychopy stimuli. Here's a solution:
# Tidy 1: just import from psychopy
import random
from psychopy import visual, event, core
# Tidy 2: create a window once. Don't close it.
win = visual.Window(
size=[500, 500],
units="pix",
fullscr=False
)
instruction_text = visual.TextStim(win, text = u'How many dots did you see?', pos=(0, 100))
answer_text = visual.TextStim(win)
# Solution: a function to collect written responses
def get_typed_answer():
answer_text.text = ''
while True:
key = event.waitKeys()[0]
# Add a new number
if key in '1234567890':
answer_text.text += key
# Delete last character, if there are any chars at all
elif key == 'backspace' and len(answer_text.text) > 0:
answer_text.text = answer_text.text[:-1]
# Stop collecting response and return it
elif key == 'return':
return(answer_text.text)
# Show current answer state
instruction_text.draw()
answer_text.draw()
win.flip()
while True:
# Prepare dot specifications
n_dots = random.randint(5, 200)
dot_xys = []
for dot in range(n_dots):
dot_x = random.uniform(-250, 250)
dot_y = random.uniform(-250, 250)
dot_xys.append([dot_x, dot_y])
# This is extremely ugly! You should generally never create a new stimulus,
# but rather update an existing one. However, ElementArrayStim currently
# does not support changing the number of elements on the go.
dot_stim = visual.ElementArrayStim(
win=win,
units="pix",
elementTex=None,
elementMask="circle",
sizes=10,
contrs=random.random(),
nElements = n_dots,
xys = dot_xys,
)
# Show it
dot_stim.draw()
win.flip()
core.wait(4)
# Collect response
print(get_typed_answer())
Upvotes: 2