Observe GUI table updates in Python

Hello,
I’ve searched and tried for several hours now but I can’t seem to figure this out. I use vtkMRMLTableNode for the table and qMRMLTableView for the GUI. How can I add an observer to the table that reacts on adding/modifying values in the cells. The only thing I found is ReferenceModifiedEvent in the vtkMRMLTableViewNode, but I couldn’t get that one to work.
Also, another question I had regarding tables are column types. I set the type of one of my columns to 1 (which as I understand it is a bool) but I don’t know how to change the cell values in the code now (SetCellText returns errors)

I hope you can understand my problem and thanks in advance for any help!

What you described should work. Could you send a link to your source code?

https://pastebin.com/raw/pXRf2aVD

This is the code I use for the table

It seems that you try to create a point list widget. There is already such widget, with lots of features and configuration options: qSlicerSimpleMarkupsWidget.

# Create a markup fiducial list
fidNode=slicer.mrmlScene.AddNewNodeByClass("vtkMRMLMarkupsFiducialNode")
fidNode.CreateDefaultDisplayNodes()
fidNode.AddFiducial(35,10,12)
fidNode.AddFiducial(15,0,5)
fidNode.AddFiducial(0,0,3)
# Create a list widget
fidListWidget=slicer.qSlicerSimpleMarkupsWidget()
fidListWidget.setMRMLScene(slicer.mrmlScene)
fidListWidget.jumpToSliceEnabled = True
fidListWidget.setCurrentNode(fidNode)
fidListWidget.show()

In your code the main issue was the you’ve observed the wrong event. This will work:

# Create table node
tableNode =  slicer.mrmlScene.AddNewNodeByClass("vtkMRMLTableNode")
col=tableNode.AddColumn()
col.SetName('Name')
col=tableNode.AddColumn()
col.SetName('Visible')
col=tableNode.AddColumn(vtk.vtkFloatArray())
col.SetName('Number')
tableNode.SetColumnType('Visible',vtk.VTK_BIT)
tableNode.AddEmptyRow()
tableNode.AddEmptyRow()
tableNode.AddEmptyRow()
tableNode.SetCellText(1,0,"ok")
tableNode.SetCellText(1,1,"1")

# Table view
tableView=slicer.qMRMLTableView()
tableView.setMRMLScene(slicer.mrmlScene)
tableView.setMRMLTableNode(tableNode)
tableView.show()

# Observe modifications

def tableModified(caller, event):
  print("Table modified")

observerTag = tableNode.AddObserver(vtk.vtkCommand.ModifiedEvent, tableModified)

Oh wow, I didn’t know there was something like that already. Thanks a lot! I will probably implement it later but for now I’ll try to get a better understanding first.
On a side node: Is it possible to get the row id that was modified via calldata or a similar function to slicer.clickedMarkupIndex? vtk.VTK_INT seems to crash slicer when calling the tableModified function.

See these examples:

https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Get_a_notification_if_a_markup_point_position_is_modified

https://www.slicer.org/wiki/Documentation/Nightly/ScriptRepository#Manipulating_objects_in_the_slice_viewer

Thank you very much - I ended up using the widget you suggested and everything is working fine now :slight_smile:

1 Like