[ctk.ctkDoubleRangeSlider()] Unable to use setRange() on this class

Hi,
Im using Slicer 4.11.0-2020-09-05 and am building a python scriptable module.

Issue
I wish to replicate the behavior of slicer.qMRMLWindowLevelWidget() as done on this line, but on my own using ctk.ctkDoubleRangeSlider(). I did not use the default slicer.qMRMLRangeWidget() since it does not seem to be using a spin box that allows floating values. But i am unable to use setRange() on ctk.ctkDoubleRangeSlider() and hence it uses the default range of [0,100]

My Code
The erroneous line has been commented here

self.uncMinSpinBox  = qt.QDoubleSpinBox()
self.uncMinSpinBox.setRange(0.0, 10.0)
self.uncMinSpinBox.setValue(0.0)
self.uncMinSpinBox.setDecimals(1)
self.uncMinSpinBox.setSingleStep(0.1)
self.uncMinSpinBox.valueChanged.connect(self._uncMinSpinBoxChanged)

self.uncMaxSpinBox  = qt.QDoubleSpinBox()
self.uncMaxSpinBox.setRange(0, 10.0)
self.uncMaxSpinBox.setValue(10.0)
self.uncMaxSpinBox.setDecimals(1)
self.uncMaxSpinBox.setSingleStep(0.1)
self.uncMaxSpinBox.valueChanged.connect(self._uncMaxSpinBoxChanged)

self.uncSlider = ctk.ctkDoubleRangeSlider()
# self.uncSlider.setRange(0.0, 10.0) # << -------------- ERRONEOUS LINE
self.uncSlider.orientation=qt.Qt.Horizontal
self.uncSlider.singleStep=0.1
self.uncSlider.setMinimumValue(0.0)
self.uncSlider.setMaximumValue(1.0)
self.uncSlider.positionsChanged.connect(self._onUncSliderChanged)

What am I missing here.

The problem is just that setRange method is not a property setter and it was not declared as Q_INVOKABLE either:

It is a very easy fix (just add Q_INVOKABLE before void).

However, you don’t need this, as slicer.qMRMLRangeWidget() uses a double spinbox and sliders. If you set a quantity then the unit and number of decimals will be determined by the unit settings in the application. If you don’t set a quantity then it will be determined automatically (and you can probably add more decimals by typing and/or by hitting Ctrl + +).

image

1 Like

+1 for making range a property

If you are looking to create a widget similar to slicer.qMRMLWindowLevelWidget where you are also using it to manage Window Level, I would suggest that your try out the latest Slicer Preview as this widget has changed since the version that you are using which is over a year old.

In the latest Slicer Preview you can do the following to set the range of the Window level bounds. Note the difference between setting the bounds versus setting the upper and lower values of the active range.

# Load sample volume
import SampleData
sampleDataLogic = SampleData.SampleDataLogic()
mrHead = sampleDataLogic.downloadMRHead()

widget = slicer.qMRMLWindowLevelWidget()
widget.setMRMLVolumeNode(mrHead)
widget.setMinMaxBounds(-200, 200)
widget.setMinMaxRangeValue(-100,100)
widget.show()

image

1 Like

Thanks @lassoan !
I followed your suggestion and did the following.

self.uncSlider2 = slicer.qMRMLRangeWidget()
self.uncSlider2.setRange(0.0, 1.0)
self.uncSlider2.singleStep=0.1 # <----- this did the trick
self.uncSlider2.valuesChanged.connect(self._onUncSliderChanged2)
viewParametersFormLayout.addRow(self.uncSlider2)

It now looks like this
qMRMLRangeWidget

But, I was unable to find (here or here) a function to avoid showing the circled item.
I may sound too pedantic, but given that I am designing this interface for clinicians, I would prefer keeping the interface as minimal as possible. I do not want the users playing with the min and max values of the range.

We don’t always expose specific API to manipulate such small details, but you can always have full access to all Qt widgets that you can use (at your won risk). Hiding the button has no risk, and probably it is not a very common need (so there would be no need to create a specific API for it), so you can just get that button and hide it:

tripleDotButton = slicer.util.findChildren(self.uncSlider2, className='QToolButton')[0]
tripleDotButton.hide()

If you need a list of child widgets (so that you know the type and name of the object), you can use slicer.util.findChildren method, specifying just the parent widget.

2 Likes