#### Howdy, Stranger!

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

Supported by

# A slider widget for OpenSesame 3.2

edited October 2019

I've seen quite a few questions about slider widgets for OpenSesame forms. A few examples of slider widgets are floating around on this forum, but these examples aren't compatible with OpenSesame 3.2. Therefore I attached a demonstration experiment (for OpenSesame 3.2) that defines a slider widget, and shows how you can use it, both in an inline_script and in a form_base item.

I hope this is useful!

(See a link to the experiment in my comment below. It appears to have gotten lost during a forum upgrade.)

• Hi @sebastiaan and @eduard

Sorry if I missed this in your code, is there a way to control for the gradations when filling the slider? I think the way it is now, it is from 0 to a 100 steps to fill in the entire slider.
But if I wanted to have a more narrow range, say 0 to 10 with increments, or 0 to 1 in increments of 0.1 (to match the current scale), is there are way to control that directly in your code?

Thanks
Helio

• Hi Helio,

The sliders goes from 0 to 1, but I would leave it that way, because that's easily converted to whatever range you need later on. If you want to control the gradation, you can adjust the script to, for example, round self._fill to 1 digit of precision, so that there are 10 steps (0, 0.1, 0.2, etc.).

You can do this in SliderWidget.coroutine(), right before self._set_fill() is called. For example like so:

def coroutine(self):

retval = None
while True:
d = yield retval
if u'pos' not in d:
continue
click_x, click_y = d[u'pos']
x, y, w, h = self.rect
if self._orientation == u'horizontal':
self._fill = 1. * (click_x - x) / w
elif self._orientation == u'vertical':
self._fill = 1. * (y + h - click_y) / h
else:
raise ValueError(u'Invalid orientation: %s' % self._orientation)
self._fill = round(self._fill, 1)
self._set_fill()

Cheers!
Sebastiaan

works perfectly.

cheers!
Helio

• Hi,

Please forgive me for my ignorance but I can't find the "attached a demonstration experiment".

any help?

SH

• Neither did I, but here it is!

• Hi,

Thank you for the code. It's a very useful widget!

I am trying to customize the slider to my needs. I want to add an image, under the slider, that changes according to the amount of fill in the slider. I am having a hard time implementing this.

I managed to add an image, but I couldn't make it change according to the fill.

Thank you

Naama

• Hi Naama,

I can't open the attachment, but conceptually, you have to draw the image to a canvas (as you probably already have and then change the image depending on the fill For example:

cv = Canvas()
cv['stim'] = Image(filepath)
cv.show()
<do stuff to get current fill>
cv['stim'].image = path_to_updated_file

Does that make sense?

Eduard

• It should be downloadable again! (We've been having some issues with the forum lately, and some attachments got lost.)

• Hi there,

A very basic question here: How can I add some text to identify what each side of the slider represents? I want to implement a slider which has possible ratings of 1 (very dissimilar) to 9 (very similar).

Any help would be greatly appreciated.

• Hi,

The slider is just a regular widget that you can add to a form. Other widgets can be added to the same form. For example, there is a text display widget. See here for more info on forms and widgets:

So basically, in the example experiment that Sebastiaan uploded, you can add in the python_example inline_script, text displays widgets that indicate the labels of the slider.

Good luck,

Eduard

• Hi @sebastiaan and @eduard,

thanks for the code above! Would it be possible to change the slider fill depending on mouse position instead of mouse click? If I wanted to have an image behind the slider, where would I add the canvas function?

• edited October 2022

Hi Dina,

I am not an expert on that, but from what I can see in the source code implementing widgets and forms it is not that trivial to change. I think I could make it work, but only by changing the source code and without testing whether anything else in Opensesame didn't break because of my changes.

To try it out yourself, you need to find two files on your system:

• libopensesame/widgets/_widgets.py
• libopensesame/widgets/_form.py

In the first one you need to change lines 192 - end with:

def on_mouse_pos(self, pos):

"""
desc:
Is called whenever the user clicks on the widget.

arguments:
pos:
desc:   An (x, y) coordinates tuple.
type:   tuple
"""

pass

def coroutine(self):

"""
desc:
Implements the interaction. This can be overridden to implement more
complicated keyboard/ mouse interactions.
"""

retval = None
while True:
d = yield retval
if d[u'type'] == u'click':
retval = self.on_mouse_click(d['pos'])
elif d[u'type'] == u'ms_pos':
retval = self.on_mouse_pos(d['pos'])
elif d[u'type'] == u'key':
retval = self.on_key_press(d[u'key'])
elif d[u'type'] == u'stop':
break

widget = Widget

In the second one, you need to replace lines 244-250 with

elif button is None:
xy, timestamp = ms.get_pos()
# Switch the focus to the newly clicked widget (if any)
widget = self.xy_to_widget(xy)
if widget is None:
continue
if focus_widget is not None:
focus_widget.focus = False
widget.focus = True
focus_widget = widget
msg = {
u'type': u'ms_pos',
u'pos': xy,
u'button': button,
u'timestamp': timestamp
}

# Send message (if any)
if msg is None:
continue
resp = coroutines[focus_widget].send(msg)
self.canvas.show()
if resp is not None and self._validator():
break
focus_widget = None

I also attach the two files here, so you can see how they are supposed to look like (maybe you can even just replace the files altogether).

It is of course not great to make your experiment work by changing the source code. So use it with care. @sebastiaan knows perhaps an easy way to integrate those changes into your experiment instead of the source code

good luck,

Eduard

Edit: The changes definitely break the text_input form, I just noticed.