Is there an easy way to modify the existing Vision slider component? I would like to change the blue track color, and make the slider object a pointed shape, instead of the circle. I was hoping there would be a different pointer object on the exchange, but did not find anything. Was going to try to script one/ build my own, but figured I would see if anybody had any recommendations first.
Probably not; some more details in this thread:
I experimented with this, and I didnât find it to difficult too do with layered shapes and scripting.
Here is the result:
Here is a tutorial for anybody who wants to replicate this:
- Create a container named CustomSliderComponent
- Use the rectangle tool to create a rectangle in the container named BackDrop that fills the entire container
- Add a slider to the container, name it CoreComponent, and resize the slider, so it completely fills the container
- Add a comma zero to the end of the background color to make the slider transparent:
- Add four custom âColorâ properties to the slider named backDropColor, leftOfPointerColor, rightOfPointerColor, and pointerColor. Then, set the colors to whatever you are going to want them to be
- Bind the BackDropâs âStroke Paintâ and âFill Paintâ properties to the Core Componentâs backDropColor custom property
- Use the rectangle tool again to draw a rectangle in the container that covers the entire slider, name it RightValues, and bind itâs âStroke Paintâ and âFill Paintâ properties to the rightOfPointerColor custom property of the CoreComponent:
- Copy the RightValues rectangle, and paste a new rectangle directly on top of the copied rectangle. I recommend using Ctrl+P (Size and Position Dialog Box) to ensure that the new rectangle is exactly on top of the RightValues rectangle.
- Give this new rectangle the name âLeftValuesâ and bind its âFill Paintâ and âStroke Paintâ properties to the CoreComponentâs leftOfPointerColor custom property. Lastly, change the width of the LeftValues rectangle to approximately half it the width of the slider:
- Use the polygon tool to create a custom shape for the pointer within the container. Then, name the shape âPointerâ and bind its âFill Paintâ property to the âpointerColorâ custom property of the CoreComponent:
- The Project Browser should now look like this:
- Add this script the Pointerâs mouseDragged event handler:
abslutePointerWidth = event.source.relWidth*(event.source.parent.getComponent('BackDrop').getSize().getWidth()/event.source.parent.getComponent('BackDrop').relWidth)
if event.x > event.source.parent.getComponent('BackDrop').getSize().getWidth()-abslutePointerWidth:
system.gui.transform(event.source, event.source.parent.getComponent('BackDrop').getSize().getWidth()-abslutePointerWidth)
elif event.x < 0:
system.gui.transform(event.source, 0)
else:
system.gui.transform(event.source, event.x)
event.source.parent.getComponent('CoreComponent').value = int(event.source.parent.getComponent('CoreComponent').minimum+((event.source.parent.getComponent('CoreComponent').maximum-event.source.parent.getComponent('CoreComponent').minimum)*event.source.relX)/(event.source.parent.getComponent('BackDrop').relWidth-event.source.relWidth))
event.source.parent.getComponent('LeftValues').relWidth = (event.source.parent.getComponent('BackDrop').relWidth-event.source.relWidth)-((event.source.parent.getComponent('BackDrop').relWidth-event.source.relWidth)-event.source.relX)
- Add this script to the CoreComponentâs mousePressed event handler:
if event.source.value > event.source.maximum:
event.source.value = event.source.maximum
elif event.source.value < event.source.minimum:
event.source.value = event.source.minimum
event.source.parent.getComponent('Pointer').relX = ((event.source.parent.getComponent('BackDrop').relWidth-event.source.parent.getComponent('Pointer').relWidth)*(event.source.value-event.source.minimum))/(event.source.maximum-event.source.minimum)
event.source.parent.getComponent('LeftValues').relWidth = (event.source.parent.getComponent('BackDrop').relWidth-event.source.parent.getComponent('Pointer').relWidth)-((event.source.parent.getComponent('BackDrop').relWidth-event.source.parent.getComponent('Pointer').relWidth)-event.source.parent.getComponent('Pointer').relX)
Iâve tested this component in a published state with different window sizes and everything works. Here is the result:
I did a custom slider with mouse press action, tag value binding changed and Mouse dragged. I have start with the tutorial of @justinedwards.jle I just dont use the componant slider of igntion to do it. Its work fine but dont have the ability to use âsnap to ticksâ and âdefer updateâ (This can be done for sure).The componant can be resize and use negative min and max value.
CustomSliderComponent.zip (12.8 KB)
I like your use of a linear scale instead of an actual slider for the core component. It works quite well!
And how could I adapt this code if the slider is in a vertical position? I tried to adapt it, but I'm not very good with coding. Can you help me? Below, I show how I tried to adapt it.
abslutePointerHeight = event.source.relHeight * (event.source.parent.getComponent('BackDrop').getSize().getHeight() / event.source.parent.getComponent('BackDrop').relHeight)
if event.y > event.source.parent.getComponent('BackDrop').getSize().getHeight() - abslutePointerHeight:
system.gui.transform(event.source, event.source.parent.getComponent('BackDrop').getSize().getHeight() - abslutePointerHeight)
elif event.y < 0:
system.gui.transform(event.source, 0)
else:
system.gui.transform(event.source, event.y)
event.source.parent.getComponent('CoreComponent').value = int(event.source.parent.getComponent('CoreComponent').minimum + ((event.source.parent.getComponent('CoreComponent').maximum - event.source.parent.getComponent('CoreComponent').minimum) * event.source.relY) / (event.source.parent.getComponent('BackDrop').relHeight - event.source.relHeight))
event.source.parent.getComponent('LeftValues').relHeight = (event.source.parent.getComponent('BackDrop').relHeight - event.source.relHeight) - ((event.source.parent.getComponent('BackDrop').relHeight - event.source.relHeight) - event.source.relY)
if event.source.value > event.source.maximum:
event.source.value = event.source.maximum
elif event.source.value < event.source.minimum:
event.source.value = event.source.minimum
event.source.parent.getComponent('Pointer').relX = ((event.source.parent.getComponent('BackDrop').relWidth - event.source.parent.getComponent('Pointer').relWidth) * (event.source.value - event.source.minimum)) / (event.source.maximum - event.source.minimum)
event.source.parent.getComponent('LeftValues').relWidth = (event.source.parent.getComponent('BackDrop').relWidth - event.source.parent.getComponent('Pointer').relWidth) - ((event.source.parent.getComponent('BackDrop').relWidth - event.source.parent.getComponent('Pointer').relWidth) - event.source.parent.getComponent('Pointer').relX)
Way back when I initially worked on this, I hadn't yet developed a reliable way to transform components within templates, so I relied on additional shapes embedded in the component to get relative dimensions. The way I do this sort of thing now is much simpler.
Here is a reworked vertical version of @gpellicelli's scale for you to study:
customVerticalSlider.zip (12.2 KB)
Thank you very much for your help. I really appreciate it
I've been studying how CustomVerticalSlider works and I've understood some things, but not all. Right now, my knowledge still doesn't reach that level. I tried to adjust it to my need, which is to make the 'value' property bidirectional and be able to write to it from a numeric text field, but I was unsuccessful in trying to adapt it. Could you help me or give me a push to solve it?
It would be tricky to convert the way I scripted it. Basically, everything needs to be flipped around so the value drives the position instead of the position driving the value. That way, every movement of the pointer sets the value property, and then the propertyChange event handler can set the position.
...or the value can be set directly without the pointer being moved, and the propertyChange event handler will then set the position.
Basically, change this:
def getValueFromPosition(self, newPosition):
# Get the min and max positions in pixels from the getMinMaxPositions custom method
minPosition, maxPosition = self.getMinMaxPositions()
# Get the min and max value custom property values from the template
maxValue = self.parent.valueMax
minValue = self.parent.valueMin
# Determine how far newPosition is between minPosition and maxPosition as a fraction
# Use a turnary operator to eliminate the possibility of dividing by zero
ratio = ((newPosition - minPosition) / (maxPosition - minPosition)) if maxPosition != minPosition else 0
# Scale the value to be between minValue and maxValue using the ratio
scaledValue = maxValue - (ratio * (maxValue - minValue))
# Set the new position custom property, so it will not need to be recalculated
# ...by the propertyChange event handler that drives the transformations
self.newPosition = newPosition
# Assign the scaled value to the templates value property
self.parent.value = scaledValue
to this:
def getPositionFromValue(self, newValue):
# Get the min and max value custom property values from the template
maxValue = self.parent.valueMax
minValue = self.parent.valueMin
# Get the min and max positions in pixels from the getMinMaxPositions custom method
minPosition, maxPosition = self.getMinMaxPositions()
# Determine how far the new value is between minPosition and maximum allowed value as a fraction
# Use a turnary operator to eliminate the possibility of dividing by zero
ratio = ((newValue - minValue) / (maxValue - minValue)) if maxValue != minValue else 0
# Scale the value to be between minPosition and maxPosition using the ratio and return it as the newPosition for the pointer
return maxPosition - (ratio * (maxPosition - minPosition))
Then, drive the transformation from the template's propertyChange event handler like this:
if event.propertyName == 'value':
pointer = event.source.getComponent('Pointer')
newPosition = pointer.getPositionFromValue(event.newValue)
system.gui.transform(pointer, newY = newPosition)
In any case, I went ahead and updated the vertical slider, so it has the desired behavior. Here it is:
customVerticalSlider_v1.1.zip (13.0 KB)