#python #plotly-dash
#python #plotly-dash
Вопрос:
Работая с plotly dash, я пытаюсь, чтобы элементы ListGroup функционировали как кнопки, которые будут обновлять свою метку при нажатии. Вот код, который работает по назначению, но я вручную создал обратный вызов для каждой кнопки.
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = (
html.Div([
dbc.ListGroup([
dbc.ListGroupItem(id="button1", n_clicks=0, action=True),
dbc.ListGroupItem(id="button2", n_clicks=0, action=True),
dbc.ListGroupItem(id="button3", n_clicks=0, action=True),
])
])
)
@app.callback(Output("button1", "children"), [Input("button1", "n_clicks")])
def clicked1(n_clicks):
return f"Button 1: clicked {n_clicks} times"
@app.callback(Output("button2", "children"), [Input("button2", "n_clicks")])
def clicked2(n_clicks):
return f"Button 2: clicked {n_clicks} times"
@app.callback(Output("button3", "children"), [Input("button3", "n_clicks")])
def clicked3(n_clicks):
return f"Button 3: clicked {n_clicks} times"
if __name__ == '__main__':
app.run_server(debug=True)
Кнопки появляются и обновляются при нажатии. График обратного вызова в меню отладки выглядит так, как я ожидаю.
Теперь я хочу заменить три функции обратного вызова только одной, используя сопоставление с образцом. Идея в том, что у меня может быть динамический список из произвольного количества элементов, и все они будут обновляться, как и ожидалось. Следуя тому, как это описано в документации, я изменяю код, чтобы использовать словари для идентификаторов в элементах и в обратном вызове.
import dash
import dash_bootstrap_components as dbc
import dash_html_components as html
from dash.dependencies import Input, Output, MATCH
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = (
html.Div([
dbc.ListGroup([
dbc.ListGroupItem(id={"type": "button", "index": 0}, n_clicks=0, action=True),
dbc.ListGroupItem(id={"type": "button", "index": 1}, n_clicks=0, action=True),
dbc.ListGroupItem(id={"type": "button", "index": 2}, n_clicks=0, action=True),
])
])
)
@app.callback(Output({"type": "button", "index": MATCH}, "children"), [Input({"type": "button", "index": MATCH}, "n_clicks")])
def clicked(n_clicks):
return f"Button clicked {n_clicks} times"
if __name__ == '__main__':
app.run_server(debug=True)
Теперь кнопки ничего не показывают (предполагая, что обратные вызовы не выполнялись), они доступны для просмотра, но при нажатии на них ничего не происходит, а график обратного вызова — беспорядок.
Насколько я могу судить, я следовал инструкциям. Я не получаю никаких ошибок, это просто не работает. Чего мне не хватает?
Комментарии:
1. Не уверен, но есть две идеи: вы пытались установить явное значение для начала
children
prop? Четныйchildren=''
. Кроме того, вы пробовали разделить компоненты на кнопку и текстовый компонент?2. Я попытался сначала явно установить дочерние элементы, это не имело никакого значения. Если выполняется обратный вызов, это устанавливает дочерние элементы, если нет, это то, на что я его установил. Я не пробовал разделять компоненты, но, поскольку мой первый пример работает, похоже, что соответствие шаблону нарушено, поэтому я тоже не вижу, чтобы это помогло.
Ответ №1:
Я счастлив, что вы решили свою проблему.
Я просто хотел бы предложить улучшение кода:
def group_item(index, click=None, action=False):
return dbc.ListGroupItem(id={"type": "button", "index": index}, n_clicks=click, action=action)
app.layout = (
html.Div([
dbc.ListGroup(
[group_item(i, click=0, action=True) for i in range(3)]
)
])
)
Надеюсь, что это может быть полезно для вас.
Ответ №2:
Оказывается, проблема была в управлении версиями.
Я установил dash с помощью anaconda, а в главном репозитории anaconda есть очень старые версии зависимостей dash. Итак, несмотря на то, что у меня была версия dash 1.16.3, а сопоставление с образцом в обратных вызовах было введено в 1.11, для сопоставления с образцом также требуется средство визуализации dash версии 1.4 или выше, и у меня был 1.1.2.
Решением для меня было установить dash из conda-forge, который имеет обновленные версии всех зависимостей dash.
conda install -c conda-forge dash