如何使 edit_traits() GUI 项响应其依赖项的变化?

How do I make an edit_traits() GUI item responsive to changes in its dependencies?

我正在设计一个 HasTraits 具有 dependent 属性的子类:

#!/usr/bin/env python

# Example for SO question on dynamically changing Dict contents.
from traits.api   import HasTraits, Dict, Property, Trait, Int, cached_property
from traitsui.api import View, Item

class Foo(HasTraits):
    "Has dependent properties, which I'd like to remain up-to-date in the GUI."

    _dicts = [
        {"zero": 0, "one": 1},
        {"zero": 1, "one": 2},
        {"zero": 2, "one": 3},
    ]

    zap = Int(0)
    bar = Property(Trait, depends_on=["zap"])
    baz = Trait(list(_dicts[0])[0], _dicts[0])

    @cached_property
    def _get_bar(self):
        return Trait(list(self._dicts)[self.zap], self._dicts)

    traits_view = View(
        Item("zap"),
        Item("bar"),
        Item("baz"),
        width=500,
        )

if __name__ == '__main__':
    Foo().configure_traits()

当我 运行 我看到这段代码时:

如果我更改 Zap 的值:

注意以下几点:

  1. Zap后,Bar的地址变了

    这意味着对 Bar 的更改正在 GUI 中动态更新,同时它仍处于打开状态;那太棒了!然而...

  2. 在 GUI 中显示 Bar 的方式不是很有用。

    我希望 Bar 显示为 Baz:可由用户选择。

我想要的是两全其美:

有谁知道我怎样才能得到这个?

我尝试了几种动态更新类似 Baz 的项目的方法,但都无济于事。 (参见 。)

我假设您希望 barbaz 都是 dict 类型(在特征 Dict 中)。实际上,预定义特征类型有默认的显示小部件,这比显示地址更有用。我相信 traitsui 不知道如何正确显示您的自定义 Trait 对象,除非您明确为其指定一个编辑器。注意,对于baz,虽然生成了下拉菜单,但它只是显示按键,这也不是很有用。

话虽如此,以下代码可能符合您的预期。

class Foo(HasTraits):
    "Has dependent properties, which I'd like to remain up-to-date in the GUI."

    _dicts = [
        {"zero": 0, "one": 1},
        {"zero": 1, "one": 2},
        {"zero": 2, "one": 3},
    ]

    zap = Int(0)
    bar = Property(Dict, depends_on=["zap"])
    baz = Trait(list(_dicts[0])[0], _dicts[0])

    @cached_property
    def _get_bar(self):
        return self._dicts[self.zap]

    traits_view = View(
        Item("zap"),
        Item("bar", style="custom"),
        Item("baz"),
        width=500,
        )

下面的代码让我得到我想要的行为:

#!/usr/bin/env python

# Example for SO question on dynamically changing Dict contents.
from traits.api   import HasTraits, Dict, Property, Trait, Int, cached_property, Enum, List
from traitsui.api import View, Item

class Foo(HasTraits):
    "Has dependent properties, which I'd like to remain up-to-date in the GUI."

    _dict = {
        "zero": 0,
        "one":  1,
        "two":  2,
    }

    _zaps = [
        ["zero", "one"],        
        ["one",  "two"],
        ["zero", "two"],
    ]
    zaps = List(_zaps[0])
    zap  = Enum([0,1,2])  # Selection of `zap` should limit the items of `_dict` available for selection.
    bar  = Enum(_zaps[0][0], values="zaps")
    bar_ = Int(_dict[_zaps[0][0]])

    def _zap_changed(self, new_value):
        self.zaps = self._zaps[new_value]
        self.bar_ = self._dict[self.bar]

    def _bar_changed(self, new_value):
        self.bar_ = self._dict[self.bar]

    traits_view = View(
        Item("zap"),
        Item("bar"),
        Item("bar_", style="readonly"),
        width=500,
        )

if __name__ == '__main__':
    Foo().configure_traits()

程序启动后立即:

并且在将 Zap 更改为 '1' 之后: