Howdy, Stranger!

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

Supported by

Changing text inside a button when clicked

Hello all,

OK so I am trying to create an Operation Span task.
What I want to have is a grid with buttons and next to each button the name of a letter (please see the pic).
Participants have to press these buttons in a correct oder and a number (the position of letter in the flux of letters just presented) appear on the button.
So far, and I do not know if it is the good strategy, I just create a loop presenting forms. Every time the participant click on a button the script update and refresh the values in the buttons with a counter.
Issue I have right now:

  • what I did might be too complicated and I wonder if something easier might not be possible;
  • when clicked, numbers appear on the button but on top of the previously presented one and I do not know how to refresh my form without pausing the script and waiting for a refresh.

OK I hope my explanation is clear.

Thank you for any help!

Comments

  • Hi Sylvain,

    Long time no see! Neither on the forum, nor in real life. I hope you're doing well.

    Your situation is a perfect example of when the newly introduced named Canvas elements come in handy. Here's one possible implementation. You could actually also use a sketchpad to draw the display and name the elements, and then update the Canvas of this sketchpad (as in the video below).

    Cheers!
    Sebastiaan

    LETTERS = 'ABCDEFGHI'
    GRID_SIZE = 100
    SPACING = 50
    
    # Prepare a Canvas() with rectangles, labels for the rectangles, and a counter
    # element that indicates the order in which the elements were clicked.
    my_canvas = Canvas()
    for letter, (x, y) in zip(LETTERS, xy_grid(3, spacing=GRID_SIZE+SPACING)):
        my_canvas['rect_%s' % letter] = Rect(
            x=x-GRID_SIZE/2, y=y-GRID_SIZE/2, w=GRID_SIZE, h=GRID_SIZE
        )
        my_canvas['label_%s' % letter] = Text(text=letter, x=x+GRID_SIZE/2+10, y=y)
        my_canvas['count_%s' % letter] = Text(text='', x=x, y=y)
    my_canvas.show()
    
    my_mouse = Mouse(visible=True)
    # Create a list of click numbers and loop until they've been exhausted
    clicks = list('123456789')
    response = ''
    while clicks:
        # Get a mouseclick and all elements that match the click coordinates.
        timestamp, (x, y), button = my_mouse.get_click()
        for element in my_canvas.elements_at(x, y):
            # Ignore everything that's not a rect
            if not element.startswith('rect'):
                continue
            element_nr = element.split('_')[1]
            response += element_nr
            count_element = 'count_%s' % element_nr 
            # Ignore elements that were already clicked
            if my_canvas[count_element].text != '':
                continue
            my_canvas[count_element].text = clicks.pop(0)
            my_canvas.show()
    # Log the response!
    responses.add(response=response)
    

    A video explanation of named elements:

    There's much bigger issues in the world, I know. But I first have to take care of the world I know.
    cogsci.nl/smathot

  • Hey Sebastian,

    Yeah long time not seeing you, I am in Germany these times. Next time I am around the lab I really have to come to say hello to everyone. Hope everything is fine for you guys! :)
    Anyway wow this canvas object is so nice and your solution helped a lot!
    I tweaked it a little bit so if anyone wants to use it to collect responses in OSPAN-like-task here is the part of the code. Will try to post the whole thing on osf anyway.

    LETTERS = 'FHJKLNPQRSTY'
    GRID_SIZE = 150
    SPACING = 70
    
    # Prepare a Canvas() with rectangles, labels for the rectangles, and a counter
    # element that indicates the order in which the elements were clicked.
    
    list_count_letter = list();
    
    my_canvas = Canvas()
    for letter, (x, y) in zip(LETTERS, xy_grid(3, spacing=GRID_SIZE+SPACING)):
    
        y = y - 50
    
        my_canvas['rect_%s' % letter] = Rect(
            x=x-GRID_SIZE/2, y=y-GRID_SIZE/2, w=GRID_SIZE, h=GRID_SIZE
        )
        my_canvas['label_%s' % letter] = Text(text=letter, x=x+GRID_SIZE/2+16, y=y)
        my_canvas['count_%s' % letter] = Text(text='', x=x, y=y)
        list_count_letter.append('count_%s' % letter)
    
    # Display intruction on top
    y_instruction = -1*((GRID_SIZE/2) + 3*(SPACING) + GRID_SIZE) - 30
    my_canvas['Instructions'] = Text(text='blablablabla', x=0, y=y_instruction)
    
    # Add a clear and OK button
    x_Clear = -1*((GRID_SIZE/2) + SPACING + 2*(GRID_SIZE))
    x_OK = 1*((GRID_SIZE/2) + SPACING + GRID_SIZE)
    
    y_Clear = 1*((GRID_SIZE/2) + 2*(SPACING) + GRID_SIZE)
    y_OK = 1*((GRID_SIZE/2) + 2*(SPACING) + GRID_SIZE)
    
    
    my_canvas['rect_Clear'] = Rect(x=x_Clear, y=y_Clear,w=GRID_SIZE, h=GRID_SIZE/2, fill=True, color='gray')
    my_canvas['rect_OK'] = Rect(x=x_OK, y=y_OK,w=GRID_SIZE, h=GRID_SIZE/2, fill=True, color='gray')
    
    my_canvas['label_Clear'] = Text(text='Clear', x=x_Clear+(GRID_SIZE/2), y=y_Clear+(GRID_SIZE/4))
    my_canvas['label_OK'] = Text(text='OK', x=x_OK+(GRID_SIZE/2), y=y_OK+(GRID_SIZE/4))
    
    # Add a string displaying the entered sequence
    y_String_Answer = 1*((GRID_SIZE/2) + SPACING + GRID_SIZE)
    my_canvas['String_Answer'] = Text(text='', x=0, y=y_String_Answer)
    
    my_canvas.show()
    
    my_mouse = Mouse(visible=True)
    # Create a list of click numbers and loop until they've been exhausted
    
    clicks = list('123456789')
    response = ''
    OK_not_pressed = True
    
    while clicks and OK_not_pressed:
        # Get a mouseclick and all elements that match the click coordinates.
        timestamp, (x, y), button = my_mouse.get_click()
        for element in my_canvas.elements_at(x, y):
            # Ignore everything that's not a rect
            if not element.startswith('rect'):
                continue
            # reinitialise if clear
            if element == 'rect_Clear':
                clicks = list('123456789')
                response = ''
                Str_Answer = ''
                for txt_count in list_count_letter:
                    my_canvas[txt_count].text = ''
                my_canvas['String_Answer'].text = response
                my_canvas.show()
                continue
            # end if OK pressed
            if element == 'rect_OK':
                OK_not_pressed = False
                continue
            element_nr = element.split('_')[1]
            response += element_nr
    
            count_element = 'count_%s' % element_nr 
            # Ignore elements that were already clicked
            if my_canvas[count_element].text != '':
                continue
            my_canvas[count_element].text = clicks.pop(0)
            my_canvas['String_Answer'].text = response
            my_canvas.show()
    # Log the response!
    responses.add(response=response)
    
Sign In or Register to comment.