I am having some issues building a GUI with traits and traitsui.
What I am trying to do can be simplified to the following:
from traits.api import List, Str, on_trait_change, Trait, HasTraits
from traitsui.api import View, Item, EnumEditor
a_names = ['aaa', 'bbb', 'ccc']
b_names = ['ddd', 'eee', 'fff']
class SomeClass( HasTraits ):
x = Str('aaa')
y = Str('bbb')
names = List( a_names, comparison_mode=2 )
select_names = Trait('list A', {'list A': a_names, 'list B': b_names},
label='Select list names')
traits_view = View(Item('select_names'),
Item('x', editor=EnumEditor( name='names' )),
Item('y', editor=EnumEditor( name='names' )))
def __init( self ):
pass
@on_trait_change( 'x' )
def _x_changed( self ):
print('x changed' )
print( self.names.index( self.x ) )
print( self.names.index( self.y ) )
@on_trait_change( 'y' )
def _y_changed( self ):
print('y changed' )
print( self.names.index( self.x ) )
print( self.names.index( self.y ) )
@on_trait_change( 'select_names', post_init=True )
def _select_names_changed( self ):
if self.select_names == 'list A':
self.x, self.y = 'aaa', 'bbb'
self.names = self.select_names_
elif self.select_names == 'list B':
self.x, self.y = 'ddd', 'eee'
self.names = self.select_names_
if __name__ == '__main__':
sc = SomeClass()
sc.configure_traits()
The idea is that I have a trait (names) representing a list, which can 'point' to two different lists of strings, depending on the value of select_names. I also have two traits x and y which are two elements of the list names. When select_names is changed, then the values of names, x and y are automatically changed. However, since the changes of traits x and y are automatically monitored, the function _x_changed and _y_changed are called before the end of _select_names_changed call, resulting in not finding x or y in names.
I tried to used to post_init=True option of on_trait_changed('select_names') to avoid this behaviour, without success.
Do you have any idea of how I should proceed ?
I finally found a workaround. In my class, I had an boolean attribute
self.locked, which value is True, if_x_changedor_y_changedare not to be executed. This gives: