Using Events on Python interface

Hello all.
I’m trying to work with observer events. Mainly, I want to invoke a function when you click on a curve markup node. I looked in the reposity and found

pointListNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)

I edited it a little to make it work for my program, but I ran into an issue similar to the one in my last post.

AttributeError: type object 'vtkSlicerMarkupsModuleMRML.vtkMRMLMarkupsNode' has no attribute 'PointClickedEvent'

If I can’t use these events on the Python interface, is there any alternative way to achieve my end goal?

Correct, there is no such event as PointClickedEvent. The reason is that clicking on a point is an interaction event that can be translated to various widget events. By default left-click is translated to WidgetEvenJumpCursor.

You can remove this default translation and add your own translation to a markupsWidget.WidgetEventCustomAction1 event, which you can observe.

Thanks for the advice! I’m now trying to get this to work with my custom module. I don’t think I’ve interpreted the examples correctly, as I’m getting an error. I put the following code in my custom module’s .py file.

# Remove old mapping
self.SetEventTranslation(vtk.vtkCommand.LeftButtonPressEvent, vtk.vtkEvent.NoModifier)
# Make left click highlight the curve in the curve list
self.SetKeyboardEventTranslation(self.WidgetStateOnWidget, vtk.vtkEvent.NoMidifier,
                                 '\0', 0, vtk.vtkCommand.LeftButtonPressEvent,
                                 self.WidgetEventCustomAction1)
# Add observer to custom action
markupsNode.AddObserver(markupsNode.ActionEvent, self.customFunction)

I get this error.

AttributeError: 'MyFirstModuleWidget' object has no attribute 'SetKeyboardEventTranslation'

When I comment out the first line, I get the same error for .SetKeyboardEventTranslation()

Instead of self. you need to use a markupsWidget. You can find example in the script repository for how to get the markups widget for a markups node.

Thanks for the help! My program is now running without any crashes, but it still doesn’t seem to work as nothing happens when I click. Here’s what I used.

  # Create new curve and place it in the nodule folder
  markupsNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLMarkupsClosedCurveNode')
  
  # Remove old mapping
  threeDViewWidget = slicer.app.layoutManager().threeDWidget(0)
  markupsDisplayableManager = threeDViewWidget.threeDView().displayableManagerByClassName(
    'vtkMRMLMarkupsDisplayableManager')
  displayNode = markupsNode.GetMarkupsDisplayNode()
  markupsWidget = markupsDisplayableManager.GetWidget(displayNode)
  markupsWidget.SetEventTranslation(markupsWidget.WidgetStateIdle, vtk.vtkCommand.LeftButtonPressEvent,
                                  vtk.vtkEvent.NoModifier)
  # Make left click highlight the curve in the curve list
  markupsWidget.SetKeyboardEventTranslation(markupsWidget.WidgetStateOnWidget, vtk.vtkEvent.NoModifier,
                                            '\0', 0, "LeftButtonPressEvent",
                                            markupsWidget.WidgetEventCustomAction1)
  # Add observer to custom action
  displayNode.AddObserver(displayNode.CustomActionEvent1, self.onSelectContour)

Your need to first remove the existing translation and then set the new translation. Also, do not mix keyboard and mouse events. Follow closely the examples in the script repository as they allow how to do this right.