How to make polygons change color when pressed

Hi! I am new to Psychopy. I am creating an updating task in which participants have to click with the mouse on polygons. I want them to change color when pressed. How can I do it by using the Builder view? Thank you so much:)

Hi There,

You want to use a code component. In the begin routine tab list your polygons:

polygons = [polygon, polygon_1]

then on every frame check if the mouse is pressed in the polygon:


for thisPolygon in polygons:
    if mouse.isPressedIn(thisPolygon):
        thisPolygon.color = 'red'

Here is a demo file. polyChangeCol.psyexp (10.9 KB)

Hope this helps,
Becca

PS. I don’t know if you want to take that online, but just incase, it will need a slight edit in the code component (change code type to ‘both’, on the right hand side change color to fillColor, since ‘color’ is ‘fillColor’ in psychoJS JSDoc: Class: Polygon)

Thank you so much, it works!

And if I want to let participants press againg on the polygon to make it return to the previous color? Is it possible?

Sure, you just need to add another “if” statement (beware on indentation!), for example:

for thisPolygon in polygons:
    if mouse.isPressedIn(thisPolygon):
		if thisPolygon.color == 'red':
			thisPolygon.color = 'blue'
		else:
			thisPolygon.color = 'red'
1 Like

It doesn’t work…

Hi There,

I think the initial reason this wouldn’t work is because the first ‘if’ statement would need a double == to test for equality (rather than assign a variable). (i.e. if thisPolygon.color == white: )

However, this is a little tricker because the ‘isPressedIn’ method will check for mouse presses every time your screen refreshes (16.66 ms on a 60Hz monitor). So, if the participant continues to hold the mouse the polygon will appear to flicker (as it transitions from one colour to the other very quickly).

A work around for this it to add a time window in which you will register ‘new’ clicks.

So, in your ‘begin routine’ you would use something like:


polygons = [polygon, polygon_2]

bufferTime=.2
clickClock=core.Clock()
lastClickTime = 0

Then in your each frame you would use something like:


for thisPolygon in polygons:
    if mouse.isPressedIn(thisPolygon):
        thisClickTime = clickClock.getTime()
        if (thisClickTime - lastClickTime) > bufferTime:
            if thisPolygon.fillColor =='red':
                thisPolygon.fillColor = 'white'
            else:
                thisPolygon.fillColor = 'red'
        lastClickTime = thisClickTime

This will only register clicks seperated by 200ms as ‘new’ clicks, and avoid the flicker effect. Here is an updated demo file polyChangeCol.psyexp (12.1 KB)

Hope this helps,
Becca

PS. I noticed that the color attribute has actually been changed to fillColor in the recent release (probably to be consistent with PsychoJS - so updated accordingly)

2 Likes

It works perfectly! Thank you so much:)

Hi Becca! This Code works perfectly in Psychopy but not in Pavlovia.
Polygons don’t change color on click and they don’t return to the previous color if I double click them.
Moreover, it is written that I have to define thisClickTime.

Any advise?

Hi Rachele,

For this ‘thisClickTime’ error you will just need to add that to the begin tab to initialize the variable on the JS side, e.g.:

thisClickTime=0

There are a few extra tweaks needed to get this online. So here is the demo I sent functioning online https://pavlovia.org/lpxrh6/change-color-on-click.

The main principles of this are as follows, change code type to ‘both’ and then make the following changes to the right hand side of the code:

  1. core.clock must be util.clock
  2. instead of thisPolygon.fillColor ==='red' use thisPolygon.fillColor['_rgb'][2] === 0 this is fetching the rgb values of the color to check if the blue channel is ‘1’ or ‘0’ (white = [1, 1, 1] red = [1, 0, 0]
  3. when assigning a new color, use thisPolygon.fillColor = new util.Color("white") instead of thisPolygon.fillColor = 'white'

Hope this helps,

Becca

1 Like

I don’t know why it doesn’t work. I put the same codes as in the demo… :frowning:

what error do you get?

Hi Becca,
I think this is a silly question but somehow I can’t figure out how to exhange the color red with blue in this code:

if ((thisPolygon.fillColor[’_rgb’][2] === 0)) {
thisPolygon.fillColor = new util.Color(‘white’);
} else {
thisPolygon.fillColor = new util.Color(‘red’);
}

So I would like the polygon to change to blue (now red) when clicked and back to white when clicked again.

Thank you!!

Hi There, did you figure this out? it would just be replacing the ‘red’ like this:


if ((thisPolygon.fillColor[’_rgb’][2] === 0)) {
thisPolygon.fillColor = new util.Color(‘white’);
} else {
thisPolygon.fillColor = new util.Color(‘blue’);
}

My problem is very similar to this one. I cannot make the thing work though. Would you look at it and tell me what you think? Thank you very much.
https://discourse.psychopy.org/t/make-image-appear-and-disappear-on-click/23007/1

Hi everyone,

I used the above mentioned code for a similar study that I am programming.
I was just wondering, using the above created code, is there a way to store the two colors of the Polygons displayed in the datafile as well, a column that contains the two colors of the left and right polygon (polygon and polygon_2) such as [white, black]?

Thanks,
Caro

Yes! You can use myLoopName.addData() in a :code: Code component to store data, the data to store would be:

[myPolygon1.fillColor, myPolygon2.fillColor]

Although, this will store it in whatever colour space you’re using. So, for example, "black" might be [-1, -1, -1] if your colour space is rgb. To get it specifically as named colours, assuming all the colours used have names, you can do:

[myPolygon1._fillColor.named, myPolygon2._fillColor.named]