pythontraitsenthoughttraitsuienaml

Enthought enaml tableeditor


I have an object with a custom table editor attached to the view. This table editor can have some of its column deleted by user input. When it is the case I call an update function, this function is also called at the instantiation of the object.

class ModelList(HasTraits):

     models = List(Instance(Model))
     table_editor = TableEditor()
     view = View(Item(name='variables', show_label=False, editor=table_editor))

     def update(self) :
         columns = []
         for model in self.models :
             columns.append(ObjectColumn(..some stuff..))
         self.table_editor.columns = columns
         self.traits_modified = True

In the enaml layout this object is referred to like that:

enamldef Main(Window):
    attr model_list
    Container:
        TraitsItem: table:
            model := model_list

It works well at instantiation however when a column is deleted it stays in the view and the terminal is filled with AttributeErrors. Also in the view the column is filled with "Format!" key word. This is all logical since the view is querying an object that does not exist anymore.

So my question is, how can I make the view completely reloads itself following change of my ModelList object?

I have also tried to redefine edit_traits() since this is the method called by enaml while constructing the view, but the function is called only once at instantiation.

Thanks a lot by advance.


Solution

  • You can provide the list of ObjectColumns as a trait on your ModelList class. Instead of defining the columns list on the TableEditor factory object, use columns_name argument instead to point to the name of the trait on ModelList. Whenever you update the list on ModelList, the TableEditor implementation should follow along.

    class ModelList(HasTraits):
        models = List(Instance(Model))
        columns = List(Instance(ObjectColumn))
        variables = ...
    
        traits_view = View(UItem('variables',
            editor=TableEditor(columns_name='columns')))
    
        def update(self):
            columns = []
            for model in self.models :
                columns.append(ObjectColumn(..some stuff..))
            self.columns = columns
    

    This is a common pattern in Traits UI. In many places, you have a choice between giving the Editor an explicit value (which is then usually static), or giving the Editor the name of a trait on the edited object that holds the (usually dynamic) value.