【问题标题】:How to trigger functions with plotly-dash button inside a tab in python?python - 如何在python选项卡内使用plotly-dash按钮触发函数?
【发布时间】:2020-07-13 11:59:16
【问题描述】:

我对编程很陌生,也很擅长冲刺。我的仪表板中有一些选项卡,在每个选项卡中我都有一个文本输入框 (int) 和一个使用输入触发一些计算的按钮。

使用以下脚本,当我选择选项卡时,会触发回调并且计算已经从文本中的空值开始,甚至在我单击按钮之前。当文本输入框为空时,我确实有一个 if 子句不返回任何内容。但这似乎不起作用。它直接进入最后的“else”子句。我该如何解决这个问题?谢谢!

@app.callback(Output('PRINTOUTPUT', 'children'),
              [Input('create_button', 'n_clicks'),
              Input('selection_tabs', 'value')],
              [State('text-input', 'value')])

def xyz (clicks, selected_tab, textinput):    
    
    changed_id = [p['prop_id'] for p in dash.callback_context.triggered][0] #To determine if n_clicks is changed. 

      
    if 'create_button' not in changed_id:
        return ""

    elif 'create_button' in changed_id:           
        if textinput =="":  #Do nothing if button is clicked and input num is blank.            
            return "No input"
        
        else: 
            #Do some calculations based on the selected tab and input
             return "Successful"

【问题讨论】:

    标签: python dashboard plotly-dash


    【解决方案1】:

    如果您的代码中存在问题,则它可能在您粘贴到问题的部分之外的其他地方。我围绕您提供的回调写了一个 MWE,它似乎按您的意图工作:

    回调的改进

    • 下面的代码包含一些改进的回调
    • dash.callback_context.triggered 列表中项目的prop_id 属性的形式为component_id.component_property。因此,如果要检查是否是'create_button'触发了回调,则应与点之前的部分进行比较(或直接与'create_button.n_clicks'进行比较)。
    • 以前,仅检查列表dash.callback_context.triggered 中的第一个元素。您可能想要检查列表中的所有元素,尽管在当前版本的 dash 中它只能包含单个组件的属性:“是 length-1 列表,除非 单个组件同时更新,例如值和时间戳或事件计数器。" (dash.callback_context.triggered)
    • 通过删除不必要的 if 语句嵌套提高了可读性,因为在 return 之后函数的执行将不会继续。

    完整代码

    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    from dash.dependencies import Input, Output, State
    
    external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
    
    app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
    
    
    tab_div = html.Div(
        dcc.Tabs(id='selection_tabs', value='tab-1', children=[
            dcc.Tab(label='Tab one', value='tab-1'),
            dcc.Tab(label='Tab two', value='tab-2'),
    ]))
    
    app.layout = html.Div(children=[
        html.H1(children='Test app'),
        tab_div,
        dcc.Input(id="text-input", type="text", placeholder=""),
        html.Div(id='PRINTOUTPUT'),
        html.Button('Click me', id='create_button')
    ])
    
    @app.callback(Output('PRINTOUTPUT', 'children'),
                  [Input('create_button', 'n_clicks'),
                  Input('selection_tabs', 'value')],
                  [State('text-input', 'value')])
    
    def xyz(clicks, selected_tab, textinput):    
    
        #To determine if n_clicks is changed. 
        changed_ids = [p['prop_id'].split('.')[0] for p in dash.callback_context.triggered]
        button_pressed = 'create_button' in changed_ids
    
        if not button_pressed:
            return ""
    
        if textinput == "":  #Do nothing if button is clicked and input num is blank.            
            return "No input"
        
        #Do some calculations based on the selected tab and input
        return "Successful"
    
    if __name__ == '__main__':
        app.run_server(debug=True)
    

    【讨论】:

      【解决方案2】:

      假设您使用dcc.Input 组件进行文本输入,它有一个可选参数value 可以在定义它时设置。默认情况下,此值设置为 python 的None。 因此,如果您在定义它时没有将此参数的值设置为空字符串"",那么将其与if 子句中的"" 进行比较将导致False,这就是为什么它总是以@ 结尾987654328@子句。

      您只需要检查您的文本输入是否为None。 尝试将您的 if 子句更改为 if textinput is None: #Do nothing if button is clicked and input num is blank. 或者您也可以在定义输入框的位置将输入框的默认值显式设置为"",但这似乎有点违反直觉。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-22
        • 2021-10-06
        • 2023-03-25
        • 2019-01-04
        • 2020-11-21
        • 1970-01-01
        • 1970-01-01
        • 2019-03-12
        相关资源
        最近更新 更多