【问题标题】:Dash Dynamic Sliders破折号动态滑块
【发布时间】:2019-02-18 19:57:28
【问题描述】:

精简问题:

我想要由下拉列表索引的滑块。因此,在下拉列表中,我将有 A、B,这将导致调整 A 值的滑块或调整 B 值的滑块。在任何时候,我都希望有一个条形图显示 A 和 B 的值。

以下是执行此操作的代码,除了一个问题:如果我将 A 的值从其默认值调整,将下拉菜单切换到 B,然后将其切换回 A,A 将重置回其默认值。

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

app.layout = html.Div([

    dcc.Dropdown(id='segselect', options = [{'label': 'A', 'value': 'A'}, 
        {'label': 'B', 'value': 'B'}]),

    html.Div(id='SliderAContainer'),
    html.Div(id='SliderBContainer'),
    dcc.Graph(id='plot_graph')

    ])

app.config['suppress_callback_exceptions']=True

@app.callback(Output('SliderAContainer', 'children'),
    [Input('segselect', 'value')])
def return_containerA(seg):
    if seg == 'A':
        return html.Div(dcc.Slider(id='A', min = 0, max = 10, step = 1))
    else:
        return html.Div(dcc.Slider(id='A', min = 0, max = 10, step = 1), style={'display': 'none'})

@app.callback(Output('SliderBContainer', 'children'),
    [Input('segselect', 'value')])
def return_containerB(seg):
    if seg == 'B':
        return html.Div(dcc.Slider(id='B', min = 0, max = 10, step = 1, value = 2))
    else:
        return html.Div(dcc.Slider(id='B', min = 0, max = 10, step = 1, value = 2), style={'display': 'none'})


@app.callback(
    Output('plot_graph', 'figure'),
    [Input('A', 'value'), Input('B', 'value')])
def plot_A(A, B):
    return {
            'data': [
                {'y': [A, B], 'type': 'bar'},
            ],
        }


if __name__ == '__main__':
    app.run_server(debug=True, port=8041, dev_tools_hot_reload=False)

如何在不触发循环依赖的情况下使 A 在将菜单切换到 B 并返回后不会重置?


原文: 这是一个有点复杂的设置,所以让我们看一个例子。

假设我正在为税单建模。我有一个公民数据库,其中列出了他们的州、婚姻状况和收入。

我想创建允许我根据婚姻状况和州调整税率的滑块,然后计算平均税单。

屏幕上的滑块太多了,所以我设置了一个下拉菜单,让我们决定按州或婚姻状况进行调整,然后设置第二个下拉菜单,让我们选择特定的州或特定的婚姻状况。所以有两个下拉菜单:

  1. 选择(州或婚姻状况)
  2. 选择一个特定的选项,例如。 Texas or Married(动态响应第一个下拉菜单)

选择了两个下拉菜单后,我想在屏幕上放置一个滑块,用于调整该州或婚姻状况的税率。 .

滑块是我卡住的地方。我需要他们提供的三个特殊功能:

  1. 如果我们调整特定州的税率,比如佛罗里达州 +5%,然后对于特定的婚姻状况,比如已婚,+4%,那么我希望已婚佛罗里达人的税率增加 +9% .这意味着我需要存储佛罗里达州的税率,即使动态生成的佛罗里达州滑块不在屏幕上。
  2. 如果我为佛罗里达州设置了税率,然后将下拉菜单从佛罗里达州切换回来,然后我希望滑块处于为佛罗里达州选择的税率。
  3. 我希望从上传的数据库中动态生成婚姻状态选项和状态选项。

到目前为止,我已经尝试了两种方法。

方法 1:创建一个滑块字典——一个用于每个州,一个用于每个婚姻状况——将所有内容放在布局中,但除了下拉菜单选择的那个之外,其他所有内容都不可见。这会中断,因为我需要计算平均税单,因此创建一个回调,将所有可能的税率增加作为输入。但是,回调仅在所有函数都被渲染时才起作用,这会中断。

方法 2:创建一个税率字典,以及一个带有动态名称的滑块。然后我可以创建所有状态和婚姻状态的动态字典,根据选定的下拉菜单和滑块进行更新。然而,为了在不清除之前选择的值的情况下进行更新,这个动态字典需要由一个将自身作为状态的回调创建,并且 Dash 不允许循环依赖,即使是状态!

我很高兴发布代码,但它会超长,所以我选择描述我在上面尝试过的方法。

【问题讨论】:

    标签: python plotly-dash


    【解决方案1】:

    查看您的代码,我知道您不介意简单地隐藏滑块。问题是您使用容器的children 属性,它在每次更改时“重新创建”滑块,从而有效地重置它们。我的建议是直接更改容器的 style 属性:

    app.layout = html.Div([
    
        dcc.Dropdown(id='segselect', options=[{'label': 'A', 'value': 'A'},
                                              {'label': 'B', 'value': 'B'}]),
    
        html.Div(dcc.Slider(id='A', min=0, max=10, step=1), id='SliderAContainer'),
        html.Div(dcc.Slider(id='B', min=0, max=10, step=1, value=2), id='SliderBContainer'),
        dcc.Graph(id='plot_graph')
    
    ])   
    
    @app.callback(Output('SliderAContainer', 'style'),
                  [Input('segselect', 'value')])
    def return_containerA(seg):
        if seg == 'A':
            return {}
        else:
            return {'display': 'none'}
    
    @app.callback(Output('SliderBContainer', 'style'),
                  [Input('segselect', 'value')])
    def return_containerB(seg):
        if seg == 'B':
            return {}
        else:
            return {'display': 'none'}
    

    请注意,我必须在布局设置中将滑块添加为子项,因为它们不再由回调函数生成。

    另外,请注意您不再需要 suppress_callback_exceptions 配置,因为滑块始终存在于 DOM 中。离开它也没有什么坏处。

    【讨论】:

    • 这太棒了!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 2011-11-05
    • 2011-12-17
    • 1970-01-01
    • 2021-12-21
    相关资源
    最近更新 更多