2011-05-24 62 views
2

我想包装一个非traits模型类,用于Python Traits。我的目标是编写一个基于Traits的用户界面来操作“外部”模型类。外部模型类已由SWIG生成,因此我不能将enthought.traits.api.HasTraits添加为祖先(我认为,虽然我可能是错的)。如何包装非Traits模型以用于Python Traits?

我目前最好的尝试是

from enthought.traits.api import HasStrictTraits, Property, Instance 

class ExternalModel(): 
    foo = 'foo' 

class TraitsModel(HasStrictTraits): 
    _e = Instance(ExternalModel) 

    def __init__(self): 
     self._e = ExternalModel() 
     self.add_trait('foo', Property(lambda  :getattr(self._e,'foo' ), 
             lambda attr:setattr(self._e,'foo',attr))) 

从而导致性状类为主TraitsModel有一个可变的财产委托给包含非性状ExternalModel实例。但是,TraitsModel.trait_names()不会将'foo'报告为公认的特征。

有关如何让TraitsModel报告链接到ExternalModel的'foo'特征的任何建议? enthought.traits.api.DelegatesTo似乎要求目标是一个Traits类(尽管我可能没有找到正确的调用,这是可能的)。

更多的MVC-ish方法可能会有一个基于特征的我的ExternalModel视图。我一直无法弄清楚基于特征视图的非Traits模型。在这方面的建议也非常受欢迎。

更新我已经想出了如何使用http://agentzlerich.blogspot.com/2011_05_01_archive.html的方法将HasTraits作为ExternalModel超类,它似乎完全浪费了时间。显然,SWIG伏都教和特质不道德的人不会动摇。在TraitsModel中包装ExternalModel,因为这个问题似乎是最好的路线。

回答

2
from enthought.traits.api import HasStrictTraits, Instance, Property 

class ExternalModel(object): 
    foo = 'foo' 

class TraitsModel(HasStrictTraits): 
    _e = Instance(ExternalModel, ExternalModel()) 

    def __init__(self): 
     ''' 
     >>> wrapper = TraitsModel() 
     >>> wrapper.foo 
     'foo' 
     >>> wrapper._e.foo = 'bar' 
     >>> wrapper.foo 
     'bar' 
     >>> wrapper.trait_names() 
     ['trait_added', '_e', 'foo', 'trait_modified'] 
     ''' 
     HasStrictTraits.__init__(self) 
     for trait in (name for name in dir(self._e) if not name.startswith('__')): 
      self.__class__.add_class_trait(
       trait, 
       Property(
        lambda:getattr(self._e, trait), 
        lambda attr:setattr(self._e, trait, attr) 
       ) 
      ) 


if __name__ == '__main__': 
    import doctest 
    doctest.testmod() 

一个相当健壮的解决方案是使用HasTraits类的add_class_trait,加上dir(self._e)得到的ExternalModel属性和一个发电机的表达/列表解析的名称来过滤魔类方法名(具有适当函数的filter将更好地包装更复杂的类)。

另外:

  • ExternalModel应继承object

  • __init__应该调用HasStrictTraits.__init__(或super(HasStrictTraits, self).__init__()

  • _e也可以在实例性状声明创建作为第二个参数使用ExternalModel()或甚至(),或作为方法TraitsModel喜欢的:

    def __e_default(self): # note preceding underscore 
        return ExternalModel() 
    

最后,我有一个slightly old copy of the Enthought APIs including Traits它可以非常方便。

+2

可以在'foo'上使用这种技术'on_trait_change'。这样,您可以监视外部对象中的更改。这可能吗? – reckoner 2013-09-24 19:48:51

+0

上面的剪切〜几乎可以工作,但是在swig导出的类中,当我调用wrapper.configure_traits()打开配置gui时,对象只是指向swig对象的指针;那里仍然需要一些映射。 – 2016-04-26 16:17:09

+0

此外,“traits.api”模块最近需要被“enthought”不合格使用。 – 2016-04-26 16:18:11

相关问题