Howdy, Stranger!

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

Supported by

Custom form widgets

Hi,
I'm new to OpenSesame but being a software developer, I appreciate the possibilities offered by the Python support.
I'm currently working on an experiment designed for tablets with heavy use of touch responses. We're using a thermometer graphic with several buttons that the user can press. To eliminate false responses (buttons are close together) we want the user to press a button twice. After the first press, the button should be somehow highlighted. The user can now change his mind and select and highlight another button or click on the same button a second time to log in the response.
So far I used a form with image_buttons, execute the form multiple times to get the multiple clicks and highlight the buttons with the draw_frame() method.
This doesn't seem very elegant, so I'm asking if there's a simpler way to develop this. Would you suggest developing my own custom widget for that and if so, is there any documentation that could help me? Or am I completely off and you guys have a better idea on how to tackle this problem?

Comments

  • edited August 2016

    Hi,

    That's an interesting question. The best solution is probably to subclass libopensesame.widgets.button, and implement the desired behavior this way. The script below illustrates the basic idea.

    There is not any documentation for this--it's outside of what normal users are expected to do. However, if you have some experience with coding, viewing the code on GitHub, which is well documented, should be fairly helpful.

    Cheers!
    Sebastiaan

    from libopensesame import widgets
    
    
    class touch_button(widgets.button):
    
        """A form button that needs to be tapped twice to be triggered."""
    
        def __init__(self, *arglist, **kwdict):
    
            """Start inactive."""
    
            widgets.button.__init__(self, *arglist, **kwdict)
            self._active = False
    
        def on_mouse_click(self, pos):
    
            """On a mouseclick, activate the current touch_button and deactivate all
            other touch_buttons when the current touch_button not yet active. If the
            current touch_button is active, accept the click as a regular button."""
    
            if self._active:
                return widgets.button.on_mouse_click(self, pos)
            for w in self.form.widgets:
                if isinstance(w, touch_button):
                    w._active = False
            self._active = True
    
        def draw_frame(self, rect=None, style='normal'):
    
            """Draw a normal frame when active, and a plain frame otherwise."""
    
            if self._active:
                widgets.button.draw_frame(self, rect, style='normal')           
            else:
                widgets.button.draw_frame(self, rect, style='plain')
    
    
    # Create a simple demo form     
    form = widgets.form(exp)
    b1 = touch_button(form, text='Button1')
    b2 = touch_button(form, text='Button2')
    form.set_widget(b1, (0,0))
    form.set_widget(b2, (0,1))
    form._exec()
    
  • Wow, thanks sebastian!
    The example works really well and shows me how to implement my own class. Would you suggest putting the code in an inline object at the beginning of the experiment or is there a better approach through import?
    I had some problems getting the thermometer to look good, as it right now consists of image_buttons with images of different sizes for which the column/row approach is not well suited.
    Another point is that we're restricted to python coded forms with this. I'm trying to make the thermometer response usable also for OpenSesame beginners. I therefore thought about providing it as a plugin, that the users could easily use in an experiment. They could then create their sketchpads graphically and ideally put the thermometer response object after the sketchpad to collect the response.
    Would this be possible? I would need to show the thermometer during stimulus presentation already, though... Maybe it's not worth the effort?
    Anyhow, I'm not sure yet which way would be the best to tackle this. Maybe you could give me some hints on this?

  • Sure, it would be possible to create your own plugin that simply renders a specific form--because that's essentially what you want to do, right? Whether it's worth the effort depends on how widely you think the thermometer response might be used. But once you've written the code as an inline script, turning it into a plugin may not be that much extra effort:

    I actually thought of a slight optimization of the code above, which I posted below. The functionality is the same, but instead of creating a new touch_button widget, it replaces the original button by the touch_button. In other words, if you add this code to the prepare phase of an inline_script at the start of your experiment (or do something analogous through a custom plugin), all buttons will be touch buttons.

    from libopensesame import widgets
    # We're going to monkeypatch the button, and we need to keep a copy of the
    # original unpatched button
    from libopensesame.widgets import original_button
    
    
    class touch_button(original_button):
    
        """A form button that needs to be tapped twice to be triggered."""
    
        def __init__(self, *arglist, **kwdict):
    
            """Start inactive."""
    
            original_button.__init__(self, *arglist, **kwdict)
            self._active = False
    
        def on_mouse_click(self, pos):
    
            """On a mouseclick, activate the current touch_button and deactivate all
            other touch_buttons when the current touch_button not yet active. If the
            current touch_button is active, accept the click as a regular button."""
    
            if self._active:
                return original_button.on_mouse_click(self, pos)
            for w in self.form.widgets:
                if isinstance(w, touch_button):
                    w._active = False
            self._active = True
    
        def draw_frame(self, rect=None, style='normal'):
    
            """Draw a normal frame when active, and a plain frame otherwise."""
    
            if self._active:
                original_button.draw_frame(self, rect, style='normal')           
            else:
                original_button.draw_frame(self, rect, style='plain')
    
    
    # Replace the standard button by our own touch button!
    widgets.button = touch_button
    
  • Nice! Thank you very much Sebastian!
    I'm first going to customize the image_button so that I'm able to provide an image to show in the "active" state of the button.
    I'll let you know about the progress then.

  • Hi,
    I really liked this functionality of touching twice in order to log the response. I wanted to know if the same is possible in checkbox? If so, what changes do I need to make in the above script?

Sign In or Register to comment.

agen judi bola , sportbook, casino, togel, number game, singapore, tangkas, basket, slot, poker, dominoqq, agen bola. Semua permainan bisa dimainkan hanya dengan 1 ID. minimal deposit 50.000 ,- bonus cashback hingga 10% , diskon togel hingga 66% bisa bermain di android dan IOS kapanpun dan dimana pun. poker , bandarq , aduq, domino qq , dominobet. Semua permainan bisa dimainkan hanya dengan 1 ID. minimal deposit 10.000 ,- bonus turnover 0.5% dan bonus referral 20%. Bonus - bonus yang dihadirkan bisa terbilang cukup tinggi dan memuaskan, anda hanya perlu memasang pada situs yang memberikan bursa pasaran terbaik yaitu http://45.77.173.118/ Bola168. Situs penyedia segala jenis permainan poker online kini semakin banyak ditemukan di Internet, salah satunya TahunQQ merupakan situs Agen Judi Domino66 Dan BandarQ Terpercaya yang mampu memberikan banyak provit bagi bettornya. Permainan Yang Di Sediakan Dewi365 Juga sangat banyak Dan menarik dan Peluang untuk memenangkan Taruhan Judi online ini juga sangat mudah . Mainkan Segera Taruhan Sportbook anda bersama Agen Judi Bola Bersama Dewi365 Kemenangan Anda Berapa pun akan Terbayarkan. Tersedia 9 macam permainan seru yang bisa kamu mainkan hanya di dalam 1 ID saja. Permainan seru yang tersedia seperti Poker, Domino QQ Dan juga BandarQ Online. Semuanya tersedia lengkap hanya di ABGQQ. Situs ABGQQ sangat mudah dimenangkan, kamu juga akan mendapatkan mega bonus dan setiap pemain berhak mendapatkan cashback mingguan. ABGQQ juga telah diakui sebagai Bandar Domino Online yang menjamin sistem FAIR PLAY disetiap permainan yang bisa dimainkan dengan deposit minimal hanya Rp.25.000. DEWI365 adalah Bandar Judi Bola Terpercaya & resmi dan terpercaya di indonesia. Situs judi bola ini menyediakan fasilitas bagi anda untuk dapat bermain memainkan permainan judi bola. Didalam situs ini memiliki berbagai permainan taruhan bola terlengkap seperti Sbobet, yang membuat DEWI365 menjadi situs judi bola terbaik dan terpercaya di Indonesia. Tentunya sebagai situs yang bertugas sebagai Bandar Poker Online pastinya akan berusaha untuk menjaga semua informasi dan keamanan yang terdapat di POKERQQ13. Kotakqq adalah situs Judi Poker Online Terpercayayang menyediakan 9 jenis permainan sakong online, dominoqq, domino99, bandarq, bandar ceme, aduq, poker online, bandar poker, balak66, perang baccarat, dan capsa susun. Dengan minimal deposit withdraw 15.000 Anda sudah bisa memainkan semua permaina pkv games di situs kami. Jackpot besar,Win rate tinggi, Fair play, PKV Games