psychopy.org | Reference | Downloads | Github

Changing line color on mouse click

OS WIn 10
PsychoPy Builderversion v2021.2.3
**Standard Standalone? YES
**What are you trying to achieve?:
Four polygon rectangles on screen. P must select 2 to confirm a rule. On mouse click i want the line color to change to indicate that it has been selected (or deselected)

**What did you try to make it work?:
I’ve downloaded versions by @wakecarter and @Becca, searched the forums and tried every permutation I can think of. There were errors associated with python syntax that I repaired and now I get no errors messges

**What specifically went wrong when you tried that?:

The program runs locally, but the linecolor does not change.

Begin Routine

clicked = 0
lineColor = 'white'
cardStim = [card1, card2, card3, card4]

Each Frame

    if mouse.isPressedIn(thiscardStim):
        if clicked == 0:
            clicked = 1
            if thiscardStim.lineColor == 'white':
                cardStim.lineColor = 'black'
    else:
        if thiscardStim.lineColor == 'black':
            cardStim.lineColor = 'white'
else:
    if clicked == 1:
        clicked = 0

Hi There,

Yes I think there is an issue with line colour at the moment online - could you instead place polygons behind the clickables and then change the colour of those? (giving the “illusion” of a line colour change?)

Thanks,
Becca

Thanks, I will give that a shot. I assume using fillColor instead?

Does the code above look ok otherwise? (I am trying my hardest to learn by trial and error)

glen

cardStim is a list and therefore doesn’t have a colour

Ok so I have this kind of working based on this example . The cards are changing colour on click, but the next set of cards is retaining the colour from the previous trial

As such, I think that I need something on the end Routine tab to clear the last trial selection.

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

Obviously I am certain this will break on upload to Pavlovia too. :face_with_raised_eyebrow:

Try the following in End Routine

for thisPolygon in polygons:
       thisPolygon.fillColor = 'white'

Perfect, thank you. Let’s hope I can get it going online next.

I keep all my templates to learn from them and to modify so hopefully can avoid asking daft questions the next time around.

Thanks again.

When you have templates that work online, feel free to share them here:

1 Like

I’ll do that. I’m building up an experiment bank for student use. I’m really not very confident in my abilities yet. Simple builder stuff I’m great with, coding not so much.

I now have a new (anticipated) problem upon upload to pavlovia
image

What have I done to try fix…? Ok so, I have checked the wrap width and spatial units on each component all are in pix, and wrap width less than the screen width. I’ve checked the sum of the pix values for each component on the horizontal and vertical axes. I’ve searched the forum and Google. I am sure it’s blindingly obvious but for the life of me I cannot see it.

Did you attempt to draw something with a size smaller than 1 pixel

If you look at Developer Tools in the browser you should be able to find out which line of code is causing the error and therefore which object.

Aha, yes. I knew that would be a stupid one and it was. Using a text component as ISI with letter height 0.1instead of 10.

So now it runs, but the cards don’t change colour when clicked.

I have the code component set to both, but I am aware of the issuesre using RGB as per post 9 here How to make polygons change color when pressed - #2 by Becca

Below is the js but I’m scared to edit it as it works (mostly).

for (var thisPolygon, _pj_c = 0, _pj_a = polygons, _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
    thisPolygon = _pj_a[_pj_c];
    if (mouse.isPressedIn(thisPolygon)) {
        thisClickTime = clickClock.getTime();
        if (((thisClickTime - lastClickTime) > bufferTime)) {
            if ((thisPolygon.fillColor === "red")) {
                thisPolygon.fillColor = "white";
            } else {
                thisPolygon.fillColor = "red";
            }
        }
        lastClickTime = thisClickTime;
    }
}

I’m part way…

for (var thisPolygon, _pj_c = 0, _pj_a = polygons, _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
    thisPolygon = _pj_a[_pj_c];
    if (mouse.isPressedIn(thisPolygon)) {
        thisClickTime = clickClock.getTime();
        if (((thisClickTime - lastClickTime) > bufferTime)) {
            if ((thisPolygon.fillColor['_rgb'][2] === 0)) {
                fillColor = new util.Color("white");
            } 
else {
                thisPolygon.fillColor = "red";
            }
        }
        lastClickTime = thisClickTime;
    }
}

but appreciate something needs to switch here too

 thisPolygon.fillColor = "red";

If you use the method of naming colours as variable in a Both component in Begin Experiment as per my crib sheet (e.g. white = [1,1,1] in Py and white = new util.Color([1,1,1]) in JS then you should be able to do the following:

clicked = 0 in Begin Routine

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

Thank you.

I am very nearly there now I think. The first card turns red on mouse, the second turns white, then on a second click turns red before it moves on. To be honest I can live with this for now, as it is for an in class exercise but it would be good to have it running perfectly too. I am making an assumption that there needs to be a clicked = 0+1 type statement/function (don’t even know what they are called!) and I have had a go to no avail.

It records the clicked polygons which is the important thing.

Sorry – I forgot to consider that aspect.

I’ve got a suggestion of something to try, which I’ve never tried before but would be cool if it works.

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

To do this you might need

for thisPolygon in polygons:
      thisPolygon.clicked = False

in Begin Routine

It doesn’t work for me, but I am learning with each one of these. Your help is greatly appreciated. I’m ok at reading code and understanding what it is trying to do, but less good at writing it from scratch.

Ok so I think I fixed it. I checked the boolean operators for js and realised they were True/False instead of true/false.

Thank you for your help @wakecarter

Wait till you see what I have in store for next week’s challenges :wink:

Best wishes
Glen

I code in Python using the Auto translate so I don’t both mentioning differences in the JS code that I know will be auto translated correctly.

1 Like

Yep. I had it switched to Both. Rookie error. On the positive side I figured that tiny bit out myself, so I’m taking that as a win, no matter how small. Couldn’t have done that without your help though. Thanks again.

1 Like