抽象与抽象;复杂IPython小部件仪表板的设计模式

抽象与抽象;复杂IPython小部件仪表板的设计模式,ipython,jupyter,ipywidgets,Ipython,Jupyter,Ipywidgets,IPywidgets手册在很大程度上非常有用,但缺少关于如何创建复杂仪表板的说明。特别是,我正试图了解我们如何: 设计抽象以帮助构建易于扩展的仪表板,仪表板包含多个相互依赖的小部件,其中一些小部件隐藏/显示其他小部件 这样做的方式允许我将所有小部件的状态设置为dict,这样我就可以随后实现按钮,将仪表板的配置保存并加载到JSON文件中 为了使这个问题更具体,我设计了一个我当前方法的最小示例,它基于我从@jasongrout上收到的;回答时,请通过在其中重新实现此示例来演示您的设计模式,确保明确满

IPywidgets手册在很大程度上非常有用,但缺少关于如何创建复杂仪表板的说明。特别是,我正试图了解我们如何:

  • 设计抽象以帮助构建易于扩展的仪表板,仪表板包含多个相互依赖的小部件,其中一些小部件隐藏/显示其他小部件
  • 这样做的方式允许我将所有小部件的状态设置为
    dict
    ,这样我就可以随后实现按钮,将仪表板的配置保存并加载到JSON文件中
  • 为了使这个问题更具体,我设计了一个我当前方法的最小示例,它基于我从@jasongrout上收到的;回答时,请通过在其中重新实现此示例来演示您的设计模式,确保明确满足上述两个标准:

    from IPython.display import display
    import IPython.display as ipd
    import ipywidgets as widgets
    import matplotlib.pyplot as plt
    
    class ModelUI:
    
        def __init__(self):
    
            self.par = dict()
            self.initUI()
    
        def initUI(self):
    
            self.funcPars = widgets.VBox()
    
            self.initLinear()
            self.initQuadratic()
            self.initFunc()
            self.initButton()
            self.initOutput()    
    
            self.controls = widgets.HBox([
                self.func, 
                self.funcPars, 
                self.plot
            ])
            self.UI = widgets.VBox([
                self.controls, 
                self.output
            ])
    
        def initFunc(self):
    
            self.func = widgets.Dropdown(
                description="Function:", 
                options=[
                    "Linear", 
                    "Quadratic"
                ])
            self.func.observe(self.updateFunc, "value")
    
            self.updateFunc(None)
    
        def initButton(self):
    
            self.plot = widgets.Button(description="Plot")
            self.plot.on_click(self.plotFunction)
    
        def updateFunc(self, change):
    
            if self.func.value == "Linear":
                self.funcPars.children = self.linPars
                self.par['func'] = "Linear"
            elif self.func.value == "Quadratic":
                self.funcPars.children = self.quadPars
                self.par['func'] = "Quadratic"
            else:
                pass
    
        def initLinear(self):
    
            self.m = widgets.FloatSlider(
                description="m", 
                min=-10, max=10, value=2)
            self.k = widgets.FloatSlider(
                description="k", 
                min=-10, max=10, value=1)
            self.linPars = [self.m, self.k]
    
            self.m.observe(self.updateLinear, "value")
            self.k.observe(self.updateLinear, "value")
    
            self.updateLinear(None)
    
        def updateLinear(self, change):
    
            self.par['m'] = self.m.value
            self.par['k'] = self.k.value
    
        def initQuadratic(self):
    
            self.a = widgets.FloatSlider(
                description="a", 
                min=-10, max=10, value=1)
            self.b = widgets.FloatSlider(
                description="b", 
                min=-10, max=10, value=2)
            self.c = widgets.FloatSlider(
                description="c", 
                min=-10, max=10, value=3)
            self.quadPars = [self.a, self.b, self.c]
    
            self.a.observe(self.updateQuadratic, "value")
            self.b.observe(self.updateQuadratic, "value")
            self.c.observe(self.updateQuadratic, "value")
    
            self.updateQuadratic(None)
    
        def updateQuadratic(self, change):
    
            self.par['a'] = self.a.value
            self.par['b'] = self.b.value
            self.par['c'] = self.c.value
    
        def initOutput(self):
    
            self.output = widgets.Output()
            self.plotFunction(None)    
    
        def plotFunction(self, change):
    
            self.function = {
                "Linear": lambda x: self.par['m']*x + self.par['k'],
                "Quadratic": lambda x: self.par['a']*x**2 + self.par['b']*x + self.par['c']
                }
            with self.output:
                ipd.clear_output()
                xvals = [ i/10 for i in range(-100,100)]
                yvals = list(map(self.function[self.par['func']], xvals))
                plt.plot(xvals,yvals)
                plt.show()
    
        def _ipython_display_(self):
    
            display(self.UI)
    
    ModelUI()