# Decoupled (custom) slice widget in messagebox

**URL:** https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215
**Category:** Development
**Tags:** views
**Created:** [October 12, 2017, 9:28pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215 "2017-10-12T21:28:39Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![che85](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/che85/32/636_2.png) [@che85](https://discourse.slicer.org/u/che85)
#### Post date: [October 12, 2017, 9:28pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/1 "2017-10-12T21:28:39Z")

</div>

Hi Developers,

I am curious if it would be possible for have a message box showing a slice widget. I somewhat “hacked” that but I am not happy with it and I would like to know if there is a clean way to do it.

I am asking because prior to doing prostate biopsy our module receives pre-procedural images. The operator has to confirm if an endo-rectal coil was used during pre-procedural acquisition.

The following screenshot displays, what I ‘hacked’ so far.

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/1/a/1a5634fd7cfa74cd10e1a8bc7493a1e16673c6fc.png)

```
class ...
  def __init__ (self, widgetName, text="", parent=None, **kwargs):
    qt.QMessageBox. __init__ (self, parent if parent else slicer.util.mainWindow())
    self.widgetName = widgetName
    self.text = text
    for key, value in kwargs.iteritems():
      if hasattr(self, key):
        setattr(self, key, value)
    self.setup()

  def setup(self):
    widget = self.layoutManager.sliceWidget(self.widgetName)
    if not widget:
      raise AttributeError("Slice widget with name %s not found" %self.widgetName)
    sliceNode = widget.sliceLogic().GetSliceNode()

    self.sliceWidget = slicer.qMRMLSliceWidget()
    self.sliceWidget.setMRMLScene(widget.mrmlScene())
    self.sliceWidget.setMRMLSliceNode(sliceNode)

    self.layout().addWidget(self.sliceWidget, 0, 1)
    self.layout().addWidget(qt.QLabel(self.text), 1 ,1)
    self.layout().addWidget(self.createHLayout(self.buttons()), 2, 1)

  def exec_(self):
      widget = self.layoutManager.sliceWidget(self.widgetName)
      self.sliceWidget.setFixedSize(widget.size)
      return qt.QMessageBox.exec_(self)

```

Thanks for any help.

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [October 12, 2017, 9:44pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/2 "2017-10-12T21:44:05Z")

</div>

You should be able to just show the slice widget directly, without a layout manager. Have you tried that?

---

<div class="post-metadata">

### Author: ![che85](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/che85/32/636_2.png) [@che85](https://discourse.slicer.org/u/che85)
#### Post date: [October 13, 2017, 1:21pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/3 "2017-10-13T13:21:52Z")

</div>

Hi Andras,

I tried the following. For any reason it displays the red slice widget, but I didn’t even specify the name…

```
sliceWidget = slicer.qMRMLSliceWidget()
sliceWidget.setMRMLScene(slicer.mrmlScene)
sliceWidget.show()

```

I would like to specify my own slice widget name, so I tried the following code which crashes Slicer:

```
sliceWidget = slicer.qMRMLSliceWidget()
sliceNode = slicer.vtkMRMLSliceNode()
sliceNode.SetLayoutName(“Black”)
slicer.mrmlScene.AddNode(sliceNode) # crashes here
sliceWidget.setMRMLSliceNode(sliceNode)

```

Did I miss something?

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [October 13, 2017, 7:45pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/4 "2017-10-13T19:45:59Z")

</div>

You need to create nodes in a certain order. I needed this some time ago and remember that Slicer crashed when that strict order was not followed bit otherwise worked. I’m not sure I can find that code, but you should be able to replicate what the layout manager does by inspecting its source code. Let me know if you have trouble finding it.

---

<div class="post-metadata">

### Author: ![che85](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/che85/32/636_2.png) [@che85](https://discourse.slicer.org/u/che85)
#### Post date: [December 7, 2017, 6:19pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/5 "2017-12-07T18:19:02Z")

</div>

> [@che85](#):
>
> sliceWidget = slicer.qMRMLSliceWidget()  
> sliceNode = slicer.vtkMRMLSliceNode()  
> sliceNode.SetLayoutName(“Black”)  
> slicer.mrmlScene.AddNode(sliceNode) # crashes here  
> sliceWidget.setMRMLSliceNode(sliceNode)

Andras I found this code [https://github.com/Slicer/Slicer/blob/dddd78bbf570644825caed947d42def104bfbc4c/Libs/MRML/Widgets/qMRMLLayoutManager.cxx#L296-L329](https://github.com/Slicer/Slicer/blob/dddd78bbf570644825caed947d42def104bfbc4c/Libs/MRML/Widgets/qMRMLLayoutManager.cxx#L296-L329)

The following code partially works partially. Unfortunately the method calls, that are commented out, are not accessible from Python.

```
sliceLogic = slicer.vtkMRMLSliceLayerLogic()
sliceLogic.SetMRMLScene(slicer.mrmlScene)
sliceNode = slicer.vtkMRMLSliceNode()
sliceNode.SetLayoutName("Black")
slicer.mrmlScene.AddNode(sliceNode)
sliceLogic.SetSliceNode(sliceNode)

lm = slicer.app.layoutManager()
sliceLayoutColor = qt.QColor.fromRgbF(sliceNode.GetLayoutColor()[0], sliceNode.GetLayoutColor()[1], sliceNode.GetLayoutColor()[2])
sliceWidget = slicer.qMRMLSliceWidget(lm.viewport())
#sliceWidget.setSliceViewName("test") # not accessible from python
sliceWidget.setObjectName("qMRMLSliceWidget" + sliceNode.GetLayoutName())
#sliceWidget.setSliceViewLabel(sliceViewLabel) # not accessible from python
#sliceWidget.setSliceViewColor(sliceLayoutColor) # not accessible from python
sliceWidget.setMRMLScene(slicer.mrmlScene)
sliceWidget.setMRMLSliceNode(sliceNode) # crashes here again

widget = qt.QWidget()
widget.setLayout(qt.QGridLayout())
widget.layout().addWidget(sliceWidget)
sliceWidget.show()

widget.show()

```

When hovering with the mouse on that sliceWidget, I am not getting the following errors:

```
Traceback (most recent call last):

 File "/Applications/Slicer.app/Contents/lib/Slicer-4.9/qt-scripted-modules/DataProbe.py", line 265, in processEvent

sliceView = slicer.app.layoutManager().sliceWidget(sliceNode.GetLayoutName()).sliceView()

AttributeError: 'NoneType' object has no attribute 'sliceView'

```

Seems like I need to register the newly created sliceWidget in the layoutManager?

---

<div class="post-metadata">

### Author: ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)
#### Post date: [December 7, 2017, 6:48pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/6 "2017-12-07T18:48:20Z")

</div>

These should be made Q\_INVOKABLE:

> <https://github.com/Slicer/Slicer/blob/61b366ef5bf0dc3c198d0bba2e509851e856cbac/Libs/MRML/Widgets/qMRMLSliceWidget.h#L82-L104>

@che85 can you try adding that to see if it fixes the python example?

---

<div class="post-metadata">

### Author: ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)
#### Post date: [December 7, 2017, 6:54pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/7 "2017-12-07T18:54:12Z")

</div>

Considering Q\_PROPERTY similar to

> <https://github.com/Slicer/Slicer/blob/61b366ef5bf0dc3c198d0bba2e509851e856cbac/Libs/MRML/Widgets/qMRMLSliceWidget.h#L52>

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [December 7, 2017, 8:54pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/8 "2017-12-07T20:54:49Z")

</div>

This works for me on latest nightly build:

```
import SampleData
volumeNode = SampleData.SampleDataLogic().downloadMRHead()

sliceWidget = slicer.qMRMLSliceWidget()
sliceWidget.setMRMLScene(slicer.mrmlScene)
sliceNode = slicer.vtkMRMLSliceNode()
sliceNode.SetName("MySlice")
sliceNode.SetLayoutName("Black")
slicer.mrmlScene.AddNode(sliceNode)
sliceWidget.setMRMLSliceNode(sliceNode)

sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)
sliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID(volumeNode.GetID())

sliceWidget.show()

```

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/3/9/393eb3ad441f250e466bf5eded9eb4c90c67e838.jpeg)

---

<div class="post-metadata">

### Author: ![che85](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/che85/32/636_2.png) [@che85](https://discourse.slicer.org/u/che85)
#### Post date: [December 7, 2017, 9:40pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/9 "2017-12-07T21:40:31Z")

</div>

I am getting a bunch of errors. I assume that the additional slice widget needs to be registered somehow, right?

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/b/1/b1f54edefaf1c19085effb94b95f8221c6418c73.png)

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [December 7, 2017, 10:02pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/10 "2017-12-07T22:02:02Z")

</div>

That’s fine, those are only reported by data probe, as it uses the layout manager to look up slice view node. I’ll fix that today. No need to register anything.

---

<div class="post-metadata">

### Author: ![che85](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/che85/32/636_2.png) [@che85](https://discourse.slicer.org/u/che85)
#### Post date: [December 7, 2017, 10:07pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/11 "2017-12-07T22:07:26Z")

</div>

Another thing is, that only “Reformat” is available in the slice orientation drop down

 ![image](https://us1.discourse-cdn.com/flex002/uploads/slicer/original/3X/4/f/4fb1840b03a0e116ed6e681921970150573c4d64.png)

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [December 8, 2017, 3:17am UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/12 "2017-12-08T03:17:55Z")

</div>

I’ve checked this again and found that the layout manager automatically creates a widget for all slice nodes that are added to the scene. The simplest is to use this widget, as there are no side effects.

```
# Load some data into the scene
import SampleData
volumeNode = SampleData.SampleDataLogic().downloadMRHead()

# Create slice node (this automatically creates a slice widget)
sliceNode = slicer.mrmlScene.CreateNodeByClass('vtkMRMLSliceNode')
sliceNode.SetName("Black")
sliceNode.SetLayoutName("Black")
sliceNode.SetLayoutLabel("BL")
sliceNode.SetOrientation("Sagittal")
sliceNode = slicer.mrmlScene.AddNode(sliceNode)

# Select background volume
sliceLogic = slicer.app.applicationLogic().GetSliceLogic(sliceNode)
sliceLogic.GetSliceCompositeNode().SetBackgroundVolumeID(volumeNode.GetID())

# Get the automatically created slice widget
lm=slicer.app.layoutManager()
sliceWidget=lm.viewWidget(sliceNode)

# Move slice widget to a different layout
# (it can be added to any other layout)
sliceWidget.setParent(None)
# Show slice widget
sliceNode.SetMappedInLayout(1)

```

Note: when you switch layouts, the widget gets hidden, so you have to call sliceNode.SetMappedInLayout(1) again.

---

<div class="post-metadata">

### Author: ![che85](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/che85/32/636_2.png) [@che85](https://discourse.slicer.org/u/che85)
#### Post date: [December 8, 2017, 3:41am UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/13 "2017-12-08T03:41:48Z")

</div>

Great! That’s working. Thanks a lot!

---

<div class="post-metadata">

### Author: ![talmazov](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/talmazov/32/3966_2.png) [@talmazov](https://discourse.slicer.org/u/talmazov)
#### Post date: [June 28, 2019, 5:14am UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/14 "2019-06-28T05:14:00Z")

</div>

This is awesome, thanks for sharing!  
Is there a way to instead of decoupling the slice widget, have it appear to the left of the current preset layout as part of the currently loaded layout template?

Do I use the sliceWidget.setParent() feature? If so, how do I obtain an instance of the currently used layout?

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [June 28, 2019, 3:52pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/15 "2019-06-28T15:52:18Z")

</div>

If you want to add views to the layout then you can customize viewer layout as shown [here](https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Customize_viewer_layout).

Views are grouped based on `viewgroup` property. To get an “independent” view, set its `viewgroup` property to a unique value.

---

<div class="post-metadata">

### Author: ![talmazov](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/talmazov/32/3966_2.png) [@talmazov](https://discourse.slicer.org/u/talmazov)
#### Post date: [June 28, 2019, 4:38pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/16 "2019-06-28T16:38:55Z")

</div>

Ok, but i’m unsure how the syntax would be. Can you please give me an example of Slicer’s preset layout named “Conventional Widescreen” where the slice nodes are grouped on the right and the 3d view on the left. I should be able to play around with that to get what I am looking for. Thanks!

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [June 28, 2019, 10:26pm UTC](https://discourse.slicer.org/t/decoupled-custom-slice-widget-in-messagebox/1215/17 "2019-06-28T22:26:35Z")

</div>

Go to the script repository link that I posted above. XML description of all the built-in view presets are linked from there.
