Folder display node ModifiedEvent doesn't get triggered from parent


I was trying to implement a callback for my folder display node, but it seems like it’s not triggering ModifiedEvent when I change the display of the parent folder.

For example, let’s say I have the following subject hierarchy:

|---- FolderB
|---- Segmentation

shNode = slicer.mrmlScene.GetSubjectHierarchyNode()
folderDisplayNode = shNode.GetItemDataNode(shNode.GetItemByName("FolderB"))
segmentationNode = shNode.GetItemDataNode(shNode.GetItemByName("Segmentation"))

def test_callback(caller, event):
    print('in here!', caller.GetName())

test = slicer.util.VTKObservationMixin()
test.addObserver(folderDisplayNode, vtk.vtkCommand.ModifiedEvent, test_callback)
test.addObserver(segmentationNode.GetDisplayNode(), vtk.vtkCommand.ModifiedEvent, test_callback)

When I change FolderA visibility, it triggers only Segmentation display node’s ModifiedEvent. I would expect it to trigger the FolderB display ModifiedEvent as well. Could you please point me to how I can fix this issue?

Thank you

A node’s modified event is only invoked if the node is modified. You can observe the node’s DisplayModified event if you want to get notified about any display node changes:

test.addObserver(segmentationNode, slicer.vtkMRMLDisplayableNode.DisplayModifiedEvent, test_callback)


My problem was actually more associated with folderDisplayNode, which is a vtkMRMLDisplayNode, not a vtkMRMLDisplayabableNode. I just added this line (test.addObserver(segmentationNode.GetDisplayNode(), vtk.vtkCommand.ModifiedEvent, test_callback) to demonstrate that changing the parent folder visibility seems to call segmentationNode.DisplayNode()'s ModifiedEvent, but not folderDisplayNode’s ModifiedEvent.

I would appreciate any pointers as to why this might be happening / how I can solve the issue.

Thank you.

Toggling visibility of the folder actually calls folderDisplayNode’s ModifiedEvent. To test, you can create a new folder, click the eye icon so that a display node gets created for it automatically, run the code snippet below, and toggle the eye icon of the folder to see the message printed:

shNode = slicer.mrmlScene.GetSubjectHierarchyNode()
folderDisplayNode = shNode.GetItemDataNode(shNode.GetItemByName('NewFolder'))
if not folderDisplayNode or not folderDisplayNode.IsA('vtkMRMLFolderDisplayNode'):
    raise RuntimeError("This folder has no display node")

def test_callback(caller, event):
    print('in here!', caller.GetName())

test = slicer.util.VTKObservationMixin()
test.addObserver(folderDisplayNode, vtk.vtkCommand.ModifiedEvent, test_callback)

Yes, that works when I have a single folder, but I’m wondering about when there’s a folder inside another folder.

|---- NewFolder

The callback is triggered when I toggle NewFolder, but not when I toggle ParentFolder.

That’s correct. A node invokes Modified event if the node is modified. A node does not invoke Modified event if a different node is modified.

Some nodes invoke custom modified events when certain properties change or some properties in related nodes change.

What is your overall goal?

If this behavior is expected, then how come the following happens?

|---- SegmentationNode

test.addObserver(SegmentationNode.GetDisplayNode(), vtk.vtkCommand.ModifiedEvent, test_callback)

Toggling ParentFolder calls test_callback.

My overall goal:
I want to update my visibility checkbox based on the “final” visibility of the NewFolder, since NewFolder is only visible when both ParentFolder and NewFolder are visible.

It looks like the folder display node explicitly invokes a Modified event on all display nodes of all its displayable node children:

The folder display node is not a displayable node, so it does not get a Modified event invokation. The code could be reorganized so that each folder display node just notifies its immediate children and then let the children folders notify their children. Do you want to give it a try to implement it?

Displaying branches that are under a “closed eye” branch in a different style (e.g., dark gray text, maybe a different icon) would be great. We’ve been thinking about implementing something like this just did not have the time. Do you plan to contribute this feature to Slicer core? Let us know how we can help.

This could be interesting for me to try, but I’ve only worked with python scripting for slicer, so I’m not very familiar with compiling it, etc. Is this something that I can get help with?

C++/Python is not a big difference, but the key question is how much you are familiar (or ready to learn) about Qt and a little about Slicer core.

If you decide to give it a try then the first step is to build Slicer from source.