Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Supported by

Setting an image_button to different positions?

Hi, i'm currently trying to make an experiment where the participant must click an image that could be in different places in the main screen. My question is how can i implement this using the widget image_button. I supposed this could be arranged by making a 10x10 grid where i can assign a position using variables for row and column defined in the loop, but i can't manage to get it working. Is there an easy way to do this? Currently my best bet is in making 100 conditional statements depending of another variable, but i suppose there's something a lot clever than that :D

Great software by the way, longtime fan.

Comments

  • Hi Sebas,

    That is certainly possible using forms and widgets. First you need to create all possible positions in your loop with two variables (row * column), but i assume you already did so?

    Then you add an inline_script where you want to create and present your widgets with the following placed in the run phase:

    from libopensesame import widgets
    
    # Creat form with 10 equally sized columns and rows
    form = widgets.form(exp, cols=[1,1,1,1,1,1,1,1,1,1], rows=[1,1,1,1,1,1,1,1,1,1])
    # Create your button, based on the image in your file pool
    image_button = widgets.image_button(form, path=pool['picture.png'],
            var='response')
    # Create widget with location based on variables from your loop
    form.set_widget(image_button, (var.column,var.row))
    form._exec()
    

    And that's it! If you are having issues with the locations, check out the documentation on custom forms:

    Currently my best bet is in making 100 conditional statements depending of another variable, but i suppose there's something a lot clever than that

    Please don't :smiley:

    Let me know whether this is what you had in mind!

    Best,
    Laurent

  • edited December 2016

    Hi, I think you can use a subloop to choose the position.

    I set up a simple experiment to illustrate:
    Insert a subloop in your formal experiment loop, and move the trial sequence in the subloop.

    In the subloop, define the position variables. I supposed that you want a 10 x 10 grid, you can use the full-factorial design to make it easier. (Remember that the count starts with 0!)

    Change 'Repeat' in the subloop to 0.01 (depends on your experimental design), so that each time you only get one of the possible positions.

    Use the form to present your image with widget image_button.
    If you want to identify the position where the image appears, use image_id to define.

    set timeout infinite
    set spacing 10
    # 10 requal rows
    set rows "1;1;1;1;1;1;1;1;1;1"
    set only_render no
    set margins "50;50;50;50"
    # 10 equal columns
    set cols "1;1;1;1;1;1;1;1;1;1"
    set _theme gray
    # Use the variables in the subloop to decide the position
    widget "[pos_col]" "[pos_row]" 1 1 image_button image_id="[position]" path="button.jpg" var=response
    

    You can go to this page for more infomation :smile:
    http://osdoc.cogsci.nl/3.1/manual/forms/widgets/image_button/

    Hope that help!

    Elliot.

  • edited December 2016

    Thanks a lot for the responses.
    I managed to set a experiment using the code in the inline provided by Knante, but my problem is adding a background image. I tried using the following script.

    bg = exp.pool[var.bg] 
    circle = exp.pool[var.circle] 
    form = widgets.form(exp, cols=[1,1,1,1,1,1,1,1,1,1,1], rows=[1,1,1,1,1,1,1,1,1,1,1])
    bg = widgets.image(form, path=pool[var.bg], adjust=False)
    circle = widgets.image(form, path=pool[var.circle], adjust=False)
    image_button = widgets.image_button(form, path=pool['bird.png'], var='response')
    form.set_widget(bg, (5,5))
    form.set_widget(circle, (5,5))
    form.set_widget(image_button, (var.column1,var.row1))
    form._exec()
    


    Where bg is a 1440x900 image and circle is a semi-transparent png with an empty circle on the center.
    I'm trying to achieve something like this:

    My issue is that i only get to display the background image. Is there any way to sort the priority of the images to show them in the expected order via the widgets?

    Thanks a lot!

  • Hi Sebas,

    If you want to add a background image to form, you have to monkey-patch it; that is, you have to replace the original form.render() function by a custom function that does the same thing but first draws a background image. This sounds more complicated than it is, as you can see in the example below (adapted from here).

    However, if I understand correctly, there are many other and easier ways to do what you want to do; for example, why not simply use a sketchpad and use variable coordinates for the bird's position?

    Cheers,
    Sebastiaan

    You can get this:

    With a script like this:

    from libopensesame import widgets
    
    
    def custom_form_render():
    
        """A custom function that overrides the original form.render(), and adds
        a background image."""
    
        form.validate_geometry()
        form.canvas.clear()
        form.canvas.image(pool['background.jpg'])
        for widget in form.widgets:
            if widget is not None:
                widget.render()
        form.canvas.show()
    
    
    form = widgets.form(exp, cols=[1,1], rows=[1,1,1,1,1])
    
    # Important bit: replace the original render function
    form.render = custom_form_render
    
    title = widgets.label(form,
        text='Indicate how much you agree with the following statement')
    question1 = widgets.label(form, text='Forms are easy', center=False)
    question2 = widgets.label(form, text='I like data', center=False)
    question3 = widgets.label(form, text='I like questionnaires', center=False)
    ratingScale1 = widgets.rating_scale(form, var='question1',
        nodes=['Agree', "Don't know", 'Disagree'])
    ratingScale2 = widgets.rating_scale(form, var='question2',
        nodes=['Agree', "Don't know", 'Disagree'])
    ratingScale3 = widgets.rating_scale(form, var='question3',
        nodes=['Agree', "Don't know", 'Disagree'])
    nextButton = widgets.button(form, text='Next')
    form.set_widget(title, (0,0), colspan=2)
    form.set_widget(question1, (0,1))
    form.set_widget(question2, (0,2))
    form.set_widget(question3, (0,3))
    form.set_widget(ratingScale1, (1,1))
    form.set_widget(ratingScale2, (1,2))
    form.set_widget(ratingScale3, (1,3))
    form.set_widget(nextButton, (0,4), colspan=2)
    form._exec()
    
Sign In or Register to comment.