Hide radio button or collapsible item slice

Hi ,
I want to hide some option for use, in slicer shown in below. This is from Landmark registration module.
Capture

Technically it should be possible to hide or show any part of the module. I have seen an example given in documentation to control widget view like this:

sliceController = slicer.app.layoutManager().sliceWidget("Red").sliceController()
# hide what is not needed
sliceController.pinButton().hide()
#sliceController.viewLabel().hide()
sliceController.fitToWindowToolButton().hide()
sliceController.sliceOffsetSlider().hide()

However, if I do not know the name, such as ‘Red’ in the given example, I can not hide.
So, my question is how can I get the names of radio buttons or collapsible items and sub-items(shown in picture) so that I can hide them to control the view?

It’s not considered good practice to rely on “reaching inside” other modules to turn on and off parts of the display, because this makes your code brittle code (it can break if the other module’s GUI changes even a little). Better practice would be to study the code you are using and generate pull requests to modularize the interface to make it more reusable (work with the developer of the module to find a good way to do this - it will probably make the original code cleaner too).

That said, for debugging and testing we do have utilities to find widgets within the application.

Hi @pieper,
Thanks, I already tried with that .
The ‘findChildren’ take atleast two arguments. So, I tried like below code and it returns an empty list:

w = slicer.modules.LandmarkRegistrationWidget
slicer.util.findChildren(w,'LandmarkRegistration')
[]

So, the list is empty. Do you have any suggestion why is happening that?

We also have a number of high-level set...Visible() functions in slicer.util for showing/hiding various parts of the application GUI. We keep maintaining these functions, so they will work even if underlying widgets slightly change.

To answer that specific question, you would have to do this:

w = slicer.modules.landmarkregistration.widgetRepresentation()
slicer.util.findChildren(w)

slicer.util.findChildren(w, name='LandmarkRegistration')  # Always specify keyword like 'name' 

That said, note that the LandmarkRegistration module is not available in the latest version of Slicer.

I’ve added an issue to fix it for latest Slicer version:

Hi @jcfr ,
I tried your code.
So the the line “slicer.util.findChildren(w)” returns a big list.

> [qSlicerScriptedLoadableModuleWidget(0x1afaa382430, name="LandmarkRegistrationModuleWidget") , QWidget(0x1afabfb0390) , ctkCollapsibleButton(0x1afb1e6a5a0) , ctkCollapsibleButton(0x1afc6173fa0) , QRadioButton(0x1afc6173420) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC61736E0), QRadioButton(0x1afc6173620) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC6173DA0), QRadioButton(0x1afc61732a0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC6173FE0), QLabel(0x1afc6173d60) , QFormLayout (QFormLayout at: 0x000001AFB21C3DC0), QVBoxLayout (QVBoxLayout at: 0x000001AFB21C4390), QFrame(0x1afc6173c20, name="EditOptionsFrame") , QVBoxLayout (QVBoxLayout at: 0x000001AFB21C3D60), QGroupBox(0x1afb1e6a6e0) , QRadioButton(0x1afb1e6a8e0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6C0A0), QRadioButton(0x1afb1e6a720) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6AA20), QFormLayout (QFormLayout at: 0x000001AFB1EDE110), QFormLayout (QFormLayout at: 0x000001AFB1EDDDB0), ctkCollapsibleButton(0x1afb1e6b020) , ctkCollapsibleButton(0x1afc6173320) , QRadioButton(0x1afc61735a0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC6173A20), QRadioButton(0x1afc61731a0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC6173F20), QLabel(0x1afc6173aa0) , QRadioButton(0x1afc6174060) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC6173960), QRadioButton(0x1afc6173760) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC61734A0), QLabel(0x1afc6173ce0) , QFormLayout (QFormLayout at: 0x000001AFB21C26B0), QVBoxLayout (QVBoxLayout at: 0x000001AFB21C3370), QVBoxLayout (QVBoxLayout at: 0x000001AFB21C2230), QFrame(0x1afc6173460, name="EditOptionsFrame") , QVBoxLayout (QVBoxLayout at: 0x000001AFB21C0AF0), QGroupBox(0x1afb1e6a660) , QRadioButton(0x1afb1e6a3e0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6AEE0), QRadioButton(0x1afb1e6a920) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6A420), QFormLayout (QFormLayout at: 0x000001AFB1EDD600), QPushButton(0x1afb1e6afe0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6A3A0), QFormLayout (QFormLayout at: 0x000001AFB1EDD0F0), ctkCollapsibleButton(0x1afabfb0810) , QWidget(0x1afb1e6ae20) , QWidget(0x1afb1e6aea0) , QGroupBox(0x1afc6c2f6b0) , QPushButton(0x1afc6c310b0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC6C2BA30), QPushButton(0x1afc6c2fb70) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFC6C310F0), QFormLayout (QFormLayout at: 0x000001AFC59170D0), QHBoxLayout (QHBoxLayout at: 0x000001AFC5917A60), QVBoxLayout (QVBoxLayout at: 0x000001AFB1EDD090), QFormLayout (QFormLayout at: 0x000001AFB1EDD3F0), QWidget(0x1afb1e693e0) , QWidget(0x1afb1e699a0) , QGroupBox(0x1afb1e69560) , QWidget(0x1afb1e6a360) , QPushButton(0x1afb1e6af20) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6ACA0), QPushButton(0x1afb1e6a9a0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6A1E0), QPushButton(0x1afb1e6ab20) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6A1A0), QHBoxLayout (QHBoxLayout at: 0x000001AFB1EDC790), QLabel(0x1afb1e6a960) , QWidget(0x1afb1e696e0) , QWidget(0x1afb1e6ae60) , QCheckBox(0x1afb1e6aaa0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6B120), QCheckBox(0x1afb1e6af60) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6B0E0), QVBoxLayout (QVBoxLayout at: 0x000001AFB1EDC430), ctkSliderWidget(0x1afb1e69720, name="ctkSliderWidget") , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6AD60), ctkDoubleSpinBox(0x1afb1e698a0, name="SpinBox") , QHBoxLayout (QHBoxLayout at: 0x000001AFB1EDB410), ctkQDoubleSpinBox(0x1afb1dc48e0) , QLineEdit(0x1afb1e6aba0, name="qt_spinbox_lineedit") , QWidgetLineControl (QWidgetLineControl at: 0x000001AFAF476580), QValidator (QValidator at: 0x000001AFB1EDB500), ctkDoubleSlider(0x1afb1e697a0, name="Slider") , QHBoxLayout (QHBoxLayout at: 0x000001AFB1EDBB30), QSlider(0x1afb1e697e0) , QHBoxLayout (QHBoxLayout at: 0x000001AFB1EDB710), QHBoxLayout (QHBoxLayout at: 0x000001AFB1EDBCE0), QLabel(0x1afb1e6ade0) , QWidget(0x1afb1e694e0) , QCheckBox(0x1afb1e69f60) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E69160), QCheckBox(0x1afb1e69320) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6A0E0), QCheckBox(0x1afb1e69620) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E696A0), QCheckBox(0x1afb1e69e20) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E69520), QHBoxLayout (QHBoxLayout at: 0x000001AFB1EDA900), QLabel(0x1afb1e69960) , QWidget(0x1afb1e69c60) , QPushButton(0x1afb1e692e0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6A0A0), QPushButton(0x1afb1e6a060) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E69CA0), QPushButton(0x1afb1e694a0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E69A60), QPushButton(0x1afb1e69420) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E69220), QHBoxLayout (QHBoxLayout at: 0x000001AFB1EDA540), QLabel(0x1afb1e69260) , QFormLayout (QFormLayout at: 0x000001AFB1EDAA80), QVBoxLayout (QVBoxLayout at: 0x000001AFB1EDA720), QFormLayout (QFormLayout at: 0x000001AFB1EDA150), qMRMLNodeComboBox(0x1afb1e627e0) , qMRMLSortFilterProxyModel (qMRMLSortFilterProxyModel at: 0x000001AFB1E63A60), qMRMLNodeFactory (qMRMLNodeFactory at: 0x000001AFB1E45A20), ctkComboBox(0x1afb1e63a20) , QComboBoxPrivateContainer(0x1afaa382f70) , QComboBoxListView(0x1afb1e632e0) , QItemSelectionModel (QItemSelectionModel at: 0x000001AFB1E45A80), QWidget(0x1afb1dbed00, name="qt_scrollarea_vcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1ED5860), QScrollBar(0x1afb1e63e60) , QWidget(0x1afb1dbf480, name="qt_scrollarea_hcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1ED5590), QScrollBar(0x1afb1e63520) , QWidget(0x1afb1e63fe0, name="qt_scrollarea_viewport") , QBoxLayout (QBoxLayout at: 0x000001AFB1ED60A0), QHBoxLayout (QHBoxLayout at: 0x000001AFB1ED6460), qMRMLSceneModel (qMRMLSceneModel at: 0x000001AFB1E62A60), QLabel(0x1afb1e69aa0) , qMRMLNodeComboBox(0x1afb1e5cda0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6B6E0), qMRMLSortFilterProxyModel (qMRMLSortFilterProxyModel at: 0x000001AFB1E5DC60), qMRMLNodeFactory (qMRMLNodeFactory at: 0x000001AFB1E44360), ctkComboBox(0x1afb1e5cde0) , QComboBoxPrivateContainer(0x1afaa382d90) , QComboBoxListView(0x1afb1e5cba0) , QItemSelectionModel (QItemSelectionModel at: 0x000001AFB1E43DA0), QWidget(0x1afb1dbb6f0, name="qt_scrollarea_vcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1DA1780), QScrollBar(0x1afb1e5dee0) , QWidget(0x1afb1dbabb0, name="qt_scrollarea_hcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1DA09A0), QScrollBar(0x1afb1e5cca0) , QWidget(0x1afb1e5cc20, name="qt_scrollarea_viewport") , QBoxLayout (QBoxLayout at: 0x000001AFB1DA2080), QHBoxLayout (QHBoxLayout at: 0x000001AFB1DA2890), qMRMLSceneModel (qMRMLSceneModel at: 0x000001AFB1E5C2A0), QLabel(0x1afb1e621e0) , qMRMLNodeComboBox(0x1afb1e570e0) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6C060), qMRMLSortFilterProxyModel (qMRMLSortFilterProxyModel at: 0x000001AFB1E56BE0), qMRMLNodeFactory (qMRMLNodeFactory at: 0x000001AFB1E41F60), ctkComboBox(0x1afb1e56220) , QComboBoxPrivateContainer(0x1afaa3827f0) , QComboBoxListView(0x1afb1e56560) , QItemSelectionModel (QItemSelectionModel at: 0x000001AFB1E421E0), QWidget(0x1afb1db7ff0, name="qt_scrollarea_vcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1DAB2C0), QScrollBar(0x1afb1e56620) , QWidget(0x1afb1db7a50, name="qt_scrollarea_hcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1DABBC0), QScrollBar(0x1afb1e569a0) , QWidget(0x1afb1e56960, name="qt_scrollarea_viewport") , QBoxLayout (QBoxLayout at: 0x000001AFB1DAB8C0), QHBoxLayout (QHBoxLayout at: 0x000001AFB1DAB2F0), qMRMLSceneModel (qMRMLSceneModel at: 0x000001AFB1E56D60), QLabel(0x1afb1e5ce60) , qMRMLNodeComboBox(0x1afabfb0b50) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFB1E6BBE0), qMRMLSortFilterProxyModel (qMRMLSortFilterProxyModel at: 0x000001AFA98FFB60), qMRMLNodeFactory (qMRMLNodeFactory at: 0x000001AFB1E40340), ctkComboBox(0x1afabfb4c10) , QComboBoxPrivateContainer(0x1afaa381210) , QComboBoxListView(0x1afabfbb6d0) , QItemSelectionModel (QItemSelectionModel at: 0x000001AFB1E3FF80), QWidget(0x1afb1db2230, name="qt_scrollarea_vcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1DA6340), QScrollBar(0x1afabfa0d10) , QWidget(0x1afb1db2190, name="qt_scrollarea_hcontainer") , QBoxLayout (QBoxLayout at: 0x000001AFB1DA6880), QScrollBar(0x1afabfbb950) , QWidget(0x1afabfbc050, name="qt_scrollarea_viewport") , QBoxLayout (QBoxLayout at: 0x000001AFB1DA65B0), QHBoxLayout (QHBoxLayout at: 0x000001AFB1DA7420), qMRMLSceneModel (qMRMLSceneModel at: 0x000001AFABFB0C50), QLabel(0x1afb1e56260) , QFormLayout (QFormLayout at: 0x000001AFB1DA66A0), QVBoxLayout (QVBoxLayout at: 0x000001AFB1DA5B60), QPushButton(0x1afabfaa110) , PythonQtSignalReceiverBase (PythonQtSignalReceiverBase at: 0x000001AFABFB1150), QVBoxLayout (QVBoxLayout at: 0x000001AFB1DA45A0)]

And this one " slicer.util.findChildren(w, name=‘LandmarkRegistration’) returns empty list []

You need to specify the name of an existing widget.

Looking at the source LandmarkRegistration.py, not all widget are associated with a name.

First find in the source what you would like to hide and if it has no name, you could call findChildren specifying a class name and then retrieving the widget by index.

Just be aware that this approach is very brittle and not sustainable.

@jcfr
Looking at the source LandmarkRegistration.py, not all widget are associated with a name.

First find in the source what you would like to hide and if it has no name, you could call findChildren specifying a class name and then retrieving the widget by index.

Can you give me a dummy example (fairly new at this) ? Did not understand it.
In the LandmarkRegistration the class name is also ‘LandmarkRegistration’. And it also returns empty list. And I am trying to hide LocalRefinement, Data probe etc. collapsible frames. :confused:

widgets are associated with a name

Qt provides a function to associate an objectName with any QObject or QWidget instance. See QObject Class | Qt Core 5.15.16

This means for a given hierarchy of QWidget, it is possible to easily lookup widget given its name.

To illustrate, I will take the Endoscopy module as an example. Looking at the source, we can see that objectName is set:

Allowing us to easily retrieve the corresponding widget instance:

>>> slicer.util.selectModule("Endoscopy")
>>> w = slicer.modules.endoscopy.widgetRepresentation()
>>> slicer.util.findChildren(w, name="inputFiducialsNodeSelector")
[qMRMLNodeComboBox(0x8a8c9f0, name="inputFiducialsNodeSelector") ]

Now, we could also achieve this without relying on the objectName using something like this:

>>> slicer.util.findChildren(w, className="qMRMLNodeComboBox")[0]
qMRMLNodeComboBox(0x8a8c9f0, name="inputFiducialsNodeSelector") 

hide […] Data probe collapsible frames

For the dataprobe, this could be achieved simply by doing this:

slicer.util.setDataProbeVisible(False)

Hi @jcfr,

The example you gave

`slicer.util.findChildren(w, name=“inputFiducialsNodeSelector”)

Yes, this works for endoscopy module. However, this is inside the ‘path’ collapsible frame which is not a ‘qMRML…type’ but ctk.ctkCollapsibleButton. So my idea is if I can hide the frame, everything inside should be hidden anyway. However when I try to access like the Fiducial example you gave in landmarkRegistration, it returns empty list.

slicer.util.findChildren(w, className="Local Refinement")
[]

You can use any of the keyword argument search parameters. Sometimes text is the most useful (but also the most potentially brittle for all the reasons we’ve stated).

In this case here’s a query that works:

slicer.util.findChildren(text="Local Refinement")[0].hide()

Hi @pieper
You are life saver! I was doing this and that last 24 hours :))
Thanks a lot .