Python 如何在ipywidgets中分离模型和视图?

Python 如何在ipywidgets中分离模型和视图?,python,model-view-controller,ipywidgets,enaml,Python,Model View Controller,Ipywidgets,Enaml,以一个简单的外汇计算器应用程序为例 我可以使用traitlets定义我的模型: 以及相应的基于打印的简单视图: class FXView: def __init__(self, model): self.model = model def show(self): print(""" domestic_qty: {:.4g} foreign_qty: {:.4g} fx_rate: {:.

以一个简单的外汇计算器应用程序为例

我可以使用traitlets定义我的模型:

以及相应的基于打印的简单视图:

class FXView:
    def __init__(self, model):
        self.model = model

    def show(self):
        print("""
        domestic_qty: {:.4g}
        foreign_qty:  {:.4g}
        fx_rate:      {:.4g}
        lock:         {}""".format(
            self.model.domestic_qty,
            self.model.foreign_qty,
            self.model.fx_rate,
            self.model.lock
        ))
下面是它的工作原理:

>> fx_model = FXModel(domestic_qty = 100., fx_rate = 200.)
>> fx_view = FXView(fx_model)
>> fx_view.show()
    domestic_qty: 100
    foreign_qty:  0.5
    fx_rate:      200
    lock:         domestic
>> fx_model.fx_rate = 195.
>> fx_view.show()
    domestic_qty: 100
    foreign_qty:  0.5128
    fx_rate:      195
    lock:         domestic
我还使用ipywidgets创建了一个视图:

import ipywidgets as widgets
domestic_label = widgets.Label("Domestic quantity")
domestic_field = widgets.FloatText()

foreign_label = widgets.Label("Foreign quantity")
foreign_field = widgets.FloatText()

fx_label = widgets.Label("Exchange rate (domestic/foreign)")
fx_field = widgets.FloatText()

lock_label = widgets.Label("If rates change, keep ")
lock_field = widgets.Dropdown(options=["domestic", "foreign"])
lock_label_post = widgets.Label('fixed')

ipyview = widgets.HBox([widgets.VBox([domestic_label, foreign_label, fx_label, lock_label]),
              widgets.VBox([domestic_field, foreign_field, fx_field, widgets.HBox([lock_field, lock_label_post])])])
看起来真的很好:

我的问题是,;如何将模型和ipyview绑定在一起?我对ENML有一些经验,可以通过操作符:=和朋友来实现


使用ipyWidget的最佳方式是什么?

好问题!我在ipywidgets上发布了一个答案:

下面介绍如何使用本文中的小部件,使用ipywidget视图创建自定义视图。关键是将属性绑定到小部件值的链接调用

将IPyWidget作为小部件导入 从traitlets导入链接 从IPython.display导入显示 类FXWidgetView: 定义初始自我,型号: self.model=model self.homesel\u label=widgets.label国内数量 self.hominal_field=widgets.FloatText self.foreign\u label=widgets.LabelForeign数量 self.foreign_field=widgets.FloatText self.fx_label=widgets.label国内/国外汇率 self.fx_field=widgets.FloatText self.lock_label=widgets.label如果速率发生变化,请保持 self.lock_field=widgets.dropdownpoptions=[国内外] self.lock\u label\u post=widgets.label'fixed' self.ipyview=widgets.HBox[widgets.VBox[self.national\u label、self.foreign\u label、self.fx\u label、self.lock\u label], widgets.VBox[self.national\u字段、self.foreign\u字段、self.fx\u字段、widgets.HBox[self.lock\u字段、self.lock\u标签\u post]] linkmodel,“国内数量”,self.national\u字段,“值” linkmodel,“外来数量”,self.foreign\u字段,“值” 链接模型,“汇率”,self.fx\u字段,“价值” 链接模型“锁定”,self.lock\u字段“值” def_ipython_显示器自身: displayself.ipyview
我要指出,Param提倡这种分离已经有一段时间了,@jbednar指出ipywidgets也可以实现方便的函数来支持这种模式。我认为这是一个好主意-拥有一些简单的便利函数,这些函数是从接受HasTraits类的interact函数中升级而来的,可以对其进行反思,并为常见情况下的不同traits提供默认小部件。

好问题!我在ipywidgets上发布了一个答案:

下面介绍如何使用本文中的小部件,使用ipywidget视图创建自定义视图。关键是将属性绑定到小部件值的链接调用

将IPyWidget作为小部件导入 从traitlets导入链接 从IPython.display导入显示 类FXWidgetView: 定义初始自我,型号: self.model=model self.homesel\u label=widgets.label国内数量 self.hominal_field=widgets.FloatText self.foreign\u label=widgets.LabelForeign数量 self.foreign_field=widgets.FloatText self.fx_label=widgets.label国内/国外汇率 self.fx_field=widgets.FloatText self.lock_label=widgets.label如果速率发生变化,请保持 self.lock_field=widgets.dropdownpoptions=[国内外] self.lock\u label\u post=widgets.label'fixed' self.ipyview=widgets.HBox[widgets.VBox[self.national\u label、self.foreign\u label、self.fx\u label、self.lock\u label], widgets.VBox[self.national\u字段、self.foreign\u字段、self.fx\u字段、widgets.HBox[self.lock\u字段、self.lock\u标签\u post]] linkmodel,“国内数量”,self.national\u字段,“值” linkmodel,“外来数量”,self.foreign\u字段,“值” 链接模型,“汇率”,self.fx\u字段,“价值” 链接模型“锁定”,self.lock\u字段“值” def_ipython_显示器自身: displayself.ipyview
我要指出,Param提倡这种分离已经有一段时间了,@jbednar指出ipywidgets也可以实现方便的函数来支持这种模式。我认为这是一个好主意-使用一些简单的便利函数,这些函数是从接受HasTraits类的interact函数中升级而来的,可以对其进行反思,并为常见情况下的不同traits提供默认小部件。

我已经复制过了我已经复制过了
import ipywidgets as widgets
domestic_label = widgets.Label("Domestic quantity")
domestic_field = widgets.FloatText()

foreign_label = widgets.Label("Foreign quantity")
foreign_field = widgets.FloatText()

fx_label = widgets.Label("Exchange rate (domestic/foreign)")
fx_field = widgets.FloatText()

lock_label = widgets.Label("If rates change, keep ")
lock_field = widgets.Dropdown(options=["domestic", "foreign"])
lock_label_post = widgets.Label('fixed')

ipyview = widgets.HBox([widgets.VBox([domestic_label, foreign_label, fx_label, lock_label]),
              widgets.VBox([domestic_field, foreign_field, fx_field, widgets.HBox([lock_field, lock_label_post])])])