Conditionally hide a button component?

OS (e.g. Win10): win 10
PsychoPy version (e.g. 1.84.x):
Standard Standalone? (y/n) If not then what?: v2022.2.4
What are you trying to achieve?: I want to conditionally show/hide a button that advances to the next trial, so that participants can only proceed if they made a ‘valid’ input.

What did you try to make it work?:
I’m not sure how to make this work. I am comfortable with coding the conditions under which the button should appear, but I don’t know how to use those conditions to control it appearing. Is there a way to simply enable/disable the button component via code? I tried setting the button to start based on a condition, but I also want it to vanish if the input starts off valid but becomes invalid.

Any pointers on this would be appreciated

If you just want to hide it (but still collect responses) then you can set its opacity to set each frame and be the value of your conditional, but to prevent it from drawing and listening altogether you’re better off using status flags. Something like:

if conditional: 
    # if condition is met...
    if button.status in (NOT_STARTED, FINISHED):
         # if button is not within its start/stop times, leave as is
         pass
    else:
        # otherwise, have it be active
        button.status = STARTED
else:
    # if condition is not met...
    if button.status in (NOT_STARTED, FINISHED):
         # if button is not within its start/stop times, leave as is
         pass
    else:
        # otherwise, pause it
        button.status = PAUSED

(in the Each Frame tab of a :code: Code component)

Thank you!

I’ve had a go at using this for my online experiment, but it doesn’t seem to stop the button being pressable. It might be an issue with the translation from python to js?

Here’s how it was translated including how i modified it to add my condition:

var _pj;
function _pj_snippets(container) {
    function in_es6(left, right) {
        if (((right instanceof Array) || ((typeof right) === "string"))) {
            return (right.indexOf(left) > (- 1));
        } else {
            if (((right instanceof Map) || (right instanceof Set) || (right instanceof WeakMap) || (right instanceof WeakSet))) {
                return right.has(left);
            } else {
                return (left in right);
            }
        }
    }
    container["in_es6"] = in_es6;
    return container;
}
_pj = {};
_pj_snippets(_pj);
if (bid_right.text.length > 0) {
  submit_button.status = PsychoJS.Status.STARTED;
} else {
    submit_button.status = PAUSED;
    }

I want the button to appear when bid_right.text.length > 0. When I run the experiment the button appears to work as it did before I added this code in ‘Each Frame’.

Do you have any ideas as to what’s going wrong here?

The first thing I notice is that your JS code still has PAUSED rather than PsychoJS.Status.PAUSED - if you right click and open Inspect can you see any errors in the console? I would have thought you’d get a “PAUSED is not defined” error

I tried inspecting, it doesn’t show an error. I then tried switching the code from from PAUSED to PsychoJS.Status.PAUSED , it still runs without an error in the console but the button is unaffected!

Had a few more attempts at this, and got the button disabling/enabling to work by simply using


if (condition) {

submit_button.status = PsychoJS.Status.STARTED;

}
else { 

submit_button.status = PsychoJS.Status.PAUSED;

}

But now, the button doesn’t visually appear, even when it is enabled and clickable! Any idea whats going wrong here?

It might need autoDraw setting - try this:

if (condition) {

submit_button.status = PsychoJS.Status.STARTED;
submit_button.setAutoDraw(true);

}
else { 

submit_button.status = PsychoJS.Status.PAUSED;
submit_button.setAutoDraw(false);

}

That sorted it, thanks!

1 Like