0

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.

Jelle
  • 690
  • 4
  • 13
  • 2
    Just for clarity, Enaml isn't really involved here. You just happen to be exposing a `traitsui` `View` through Enaml's `TraitsItem` component, but the `TableEditor` is part of the `traitsui` framework, and its behavior is independent of Enaml. You will see this behavior just using `.edit_traits()/.configure_traits()` methods to view the GUI with just `traitsui`. I recommend removing the `enaml` tag from this question. – Robert Kern Apr 23 '13 at 19:45
  • I think that makes it extra interesting Robert, demonstrating that traitui and enaml can be work well combined. That's pretty relevant info – Jelle Apr 29 '13 at 18:57

1 Answers1

2

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.

Robert Kern
  • 13,118
  • 3
  • 35
  • 32