更改 Dash 应用中按钮 n_click 的值

Change the value of n_click of button in Dash app

我正在尝试创建一个应用程序来记录按钮 A 和按钮 B 被点击的次数。我通过检查每个按钮的 n_click 值并将它们用作回调中的输入来做到这一点。我还想做的是,如果按钮 B 的 n_clicks 超过按钮 A 的 n_clicks,则将两个按钮的 n_click 设置为零。

在 Dash 中有没有这样的实现?或者我是否需要将变量存储在存储器中,然后在每次单击按钮时更新它们?

编辑: 下面接受的答案需要 Dash 1.20.0。我必须将我的版本从 1.18.1 升级到 1.20.0 才能获得此功能。

无需做任何复杂的事情,只需将按钮的 n_clicks 属性 作为回调的输出,并根据需要将 return 归零。没有什么可以阻止您使用与同一回调的 InputOutput 相同的属性。这是一个最小的例子:

import dash
from dash.dependencies import Input, Output
import dash_html_components as html

app = dash.Dash(__name__)

app.layout = html.Div([
    html.Button('Button 1', id='btn1', n_clicks=0),
    html.Button('Button 2', id='btn2', n_clicks=0),
    html.Div(id='msg-container')
])

@app.callback(Output('msg-container', 'children'),
              Output('btn1', 'n_clicks'),
              Output('btn2', 'n_clicks'),
              Input('btn1', 'n_clicks'),
              Input('btn2', 'n_clicks'))
def displayClick(btn1, btn2):
    if btn2 > btn1:
        btn1, btn2 = 0, 0
    msg = "Button 1 clicked {} times, Button 2 clicked {} times".format(btn1, btn2)
    return msg, btn1, btn2

if __name__ == '__main__':
app.run_server(debug=True)

下面的方法适用于 dash 版本 1.19.0 到当前版本 1.20.0(可能更高版本)。

[1.19.0] - 2021-01-19: Adds support for callbacks which have overlapping inputs and outputs. Combined with dash.callback_context this addresses many use cases which require circular callbacks.

https://github.com/plotly/dash/blob/dev/CHANGELOG.md#added-1


正如您已经说过的,您可以使用 n_clicks 属性 按钮的数量以获取每个按钮被点击的次数。

n_clicks 也可以使用常规设置 Output.

...Or do I need to store variables in storage and then update them everytime a button is clicked?

n_clicksdash.callback_context 为您跟踪这个,所以我认为您也不需要自己跟踪它。

In addition to event properties like n_clicks that change whenever an event happens (in this case a click), there is a global variable dash.callback_context, available only inside a callback.

https://dash.plotly.com/advanced-callbacks

如何实现的示例(上面链接的文档中高级回调示例的调整版本):

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

app = dash.Dash(__name__)

app.layout = html.Div(
    [
        html.Button("Button A", id="btn-a"),
        html.Button("Button B", id="btn-b"),
        html.Div(id="container"),
    ]
)


@app.callback(
    Output("container", "children"),
    Output("btn-a", "n_clicks"),
    Output("btn-b", "n_clicks"),
    Input("btn-a", "n_clicks"),
    Input("btn-b", "n_clicks"),
    prevent_initial_call=True,
)
def display(n_clicks_a, n_clicks_b):
    ctx = dash.callback_context

    ctx_msg = json.dumps(
        {"states": ctx.states, "triggered": ctx.triggered, "inputs": ctx.inputs},
        indent=2,
    )

    if n_clicks_a is not None and n_clicks_b is not None and n_clicks_b > n_clicks_a:
        return html.Pre(ctx_msg), 0, 0

    return html.Pre(ctx_msg), n_clicks_a, n_clicks_b


if __name__ == "__main__":
    app.run_server(debug=True)

除了使用 Input 你还可以使用 State 得到 n_clicks 如果你 不希望回调在 n_clicks 发生变化时触发,但您确实希望访问其值。