Using InstanceEditor to select from Instances, combobox options not updated correctly when Instance options change
Closed this issue · 1 comments
MWE:
from traits.api import Button, HasTraits, Instance, List, observe, Str
from traitsui.api import (
InstanceEditor,
Item,
OKCancelButtons,
UCustom,
UItem,
View,
)
class Account(HasTraits):
name = Str()
traits_view = View(
Item("name"),
buttons=OKCancelButtons
)
class AccountManager(HasTraits):
new_account = Button()
accounts = List(Instance(Account))
#: Selected project
selected_account = Instance(Account)
def _accounts_default(self):
return [Account(name='A')]
@observe('new_account')
def _add_new_account(self, event):
new = Account()
new.configure_traits()
self.accounts.append(new)
def _selected_account_default(self):
return self.accounts[0]
traits_view = View(
UCustom(
'selected_account',
editor=InstanceEditor(
name='accounts',
)
),
UItem('new_account'),
)
if __name__=='__main__':
AccountManager().configure_traits()
yields:
show_bug.mov
If you replace
new = Account()
new.configure_traits()
in _add_new_account
with new = Account(name='B')
, things work as expected:
show_bug2.mov
Ah I think I see the problem. I added the following print statements:
@observe('new_account')
def _add_new_account(self, event):
print('a')
new = Account()
print('b')
new.configure_traits()
print('c')
self.accounts.append(new)
print('d')
and in traitsui.qt4.instance_editor.CustomEditor.rebuild_items
I print "rebuild_items" at the start of the method call.
When clicking "new account" I immediately see:
a
b
c
rebuild_items
d
before interacting with the configure_traits
created ui for the new Account at all.
So, for example a "fix" is to simply replace the configure_traits
call with new.configure_traits(kind='livemodal')
and then rebuild_items
will get called after the account name is set, like we want it to.
There is still a problem tough, in that if the name trait for an account is modified, that does not get reflected by the text displayed in the combobox.
This is because the current observe statement is:
self._object.observe(
self.rebuild_items, self._name + ".items", dispatch="ui"
)
ie in this case we only rebuild the items when the acccounts
list changes. However we don't update when the name of an item changes.
EDIT: I have an attempt at a fix for this in #1725