I am stumped trying to create a visual countdown timer for participants. I have a task in which participants have 7 seconds to respond and I want them to easily how much time they have. I want one solid bar to move from the far right of the top of the screen to the far left of the top of the screen, proportional to the length of the countdown.
I first tried to create a rectangle that I reduced in width until the timer runs out.
import time import sys from psychopy import visual,event,core win = visual.Window([1536,864], color="black", fullscr=True,allowGUI=False, winType='pyglet',monitor="testMonitor", units="pix") #open a window square = visual.Rect(win,lineColor="black",fillColor="blue",size=[1536,100],pos =(0,0), units = 'pix') def countdownTracker(time): timer = core.CountdownTimer(time) while timer.getTime() > 0: #until the timer is negative, after which time has elapsed width = timer.getTime()*400 #gets the current time on the countdown clock and multiples it by a constant for scaling square.size = [width,100] #changes the width of the rectangle, proportional to the timer, about 0.017 pix smaller per cycle square.pos -= 97 #changes the position of the x-axis of the square, so that it decreases in size from right to left without moving (approximate) square.draw() #draw rectangle win.flip() #make the rectangle visible countdownTracker(5) core.quit() win.close()
However, I didn’t like that solution, because:
- Despite that I set the width of the rectangle equal to the width of the screen, the rectangle was not the full width of the screen.
- Balancing how much the width reduces every repeat with changing the position was too finicky. The amount that I scaled the width and the position by was plug and chug. These were poor solutions, which is what caused me to re-think my approach. (There is probably an elegant solution based on frame rates and how often the code will cycle through this loop, but I didn’t get there).
That is when I went back to the API and found visual.Line. This solution appeared much more elegant. I was able to draw a line the entire width of the screen using the dimensions of win. I also thought it that I could change the end point of the line in the ‘while’ loop, but with a fixed starting point. Thus, there is no balance between the width of the shape and its position.
timer = core.CountdownTimer(5) while timer.getTime() > 0: line.end -= 5.1 line.draw() win.flip()
However, the line does not change its shape at all, despite that this code does seem to access and make calculations on the end point. Can someone please help me understand why I cannot update and re-draw a line with a new endpoint within a loop? Also, I chose to reduce the end-point by 5.1, because, on average, this code cycles through the loop 301 times and the screen width divided by 301 is ~5.1 If anyone has a more elegant solution for that, too, that would be great. I can’t seem to wrap my head around what to do, here.