Use same mouse event as segment editor paint effect

Hello everyone,

I used vtkcommand mouse events with the interactor style of three render windows (Red, Green, and Yellow). These mouse events triggered my custom callback functions. Everything worked until I add the segment editor widget and active paint effect. In the code, I added observers to the vtkInteractorStyle object after I activated the paint effect.

Expect to see: Both the paint effect and my callback functions work simultaneously.
Actually see: Only the paint effect and the callback function connected with leftbuttonrelease were called when I double-clicked on the render window.

Some thought:
In the paint effect, it uses the same mouse events as well. This might cause a problem.

Already tried:

  1. Set the priority of my observers to 2.0
  2. Add observers before activating the paint effect
  3. Move my observers and callback functions to another thread

Thank you for any help and insight into the reasons behind this.

If you want to hijack events from the Segment Editor then you need to specify an observer with high priority and return with 0 from your event callback function (which means that the event is not aborted but other observers get a chance to process it).

1 Like

In qMRMLSegmentEditorWidget.cxx, it sets the priority of the observers to 1.0 in setupViewObservations(). I set mine to any number larger than 1.0 but it still couldn’t hijack the events from the Segment Editor.

Could you send a link to the source code of your module or send a standalone Python code snippet that reproduces the behavior?

Please provide code that I can copy-paste into the Python console in Slicer and you would expect to work.

import logging
import slicer
import vtk
import SampleData

def onPress(arg1, arg2):
    logging.info("Press")

def onRelease(arg1, arg2):
    logging.info("Release")

lm = slicer.app.layoutManager()
rw = lm.sliceWidget("Red").sliceView().renderWindow()
style = rw.GetInteractor().GetInteractorStyle()

style.AddObserver(vtk.vtkCommand.LeftButtonPressEvent, onPress, 10.0)
style.AddObserver(vtk.vtkCommand.LeftButtonReleaseEvent, onRelease, 10.0)

# Load master volume
sampleDataLogic = SampleData.SampleDataLogic()
masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()

# Create segmentation
segmentationNode = slicer.vtkMRMLSegmentationNode()
slicer.mrmlScene.AddNode(segmentationNode)
segmentationNode.CreateDefaultDisplayNodes() # only needed for display
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)

# Create segment editor to get access to effects
segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
# To show segment editor widget (useful for debugging): segmentEditorWidget.show()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
slicer.mrmlScene.AddNode(segmentEditorNode)
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

# Run segmentation
segmentEditorWidget.setActiveEffectByName("Paint")

After activating the paint effect, onPress isn’t called when left button is pressed, and onRelease is called when left button is double clicked.

Thank you for your help!

Hi @lassoan, do you have any idea about this? Any thoughts would be helpful. Thank you!

Thank you, the script was very helpful. It was almost perfect, the only mistake was that the observer was added to the interactor style, while it should have been added to the interactor (because the interactor style only invokes event if the event is not processed):

import logging
import slicer
import vtk
import SampleData

def onPress(arg1, arg2):
    logging.info("Press")

def onRelease(arg1, arg2):
    logging.info("Release")

lm = slicer.app.layoutManager()

interactor = lm.sliceWidget("Red").sliceView().interactorStyle().GetInteractor()
interactor.AddObserver(vtk.vtkCommand.LeftButtonPressEvent, onPress, 10.0)
interactor.AddObserver(vtk.vtkCommand.LeftButtonReleaseEvent, onRelease, 10.0)

# Load master volume
sampleDataLogic = SampleData.SampleDataLogic()
masterVolumeNode = sampleDataLogic.downloadMRBrainTumor1()

# Create segmentation
segmentationNode = slicer.vtkMRMLSegmentationNode()
slicer.mrmlScene.AddNode(segmentationNode)
segmentationNode.CreateDefaultDisplayNodes() # only needed for display
segmentationNode.SetReferenceImageGeometryParameterFromVolumeNode(masterVolumeNode)

# Create segment editor to get access to effects
segmentEditorWidget = slicer.qMRMLSegmentEditorWidget()
# To show segment editor widget (useful for debugging): segmentEditorWidget.show()
segmentEditorWidget.setMRMLScene(slicer.mrmlScene)
segmentEditorNode = slicer.vtkMRMLSegmentEditorNode()
slicer.mrmlScene.AddNode(segmentEditorNode)
segmentEditorWidget.setMRMLSegmentEditorNode(segmentEditorNode)
segmentEditorWidget.setSegmentationNode(segmentationNode)
segmentEditorWidget.setMasterVolumeNode(masterVolumeNode)

# Run segmentation
segmentEditorWidget.setActiveEffectByName("Paint")