Python Dash: скрыть компонент с одним событием и сделать его видимым с другим, созданным с помощью обратного вызова - PullRequest
0 голосов
/ 09 февраля 2019

Вот «почти» рабочий пример того, что я хочу сделать с Dash.Почти потому, что этот код работает, но отсутствует часть того, что я намереваюсь сделать, но когда я пытаюсь реализовать эту другую часть, я получаю ошибку.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
app.config['suppress_callback_exceptions']=True
image = "tmpimg.png"

app.layout = html.Div([
       html.Div([
       html.Div([
           html.Button('Load image', id='load-button'),
           dcc.Upload(
                   id='upload-data',
                   children=html.Button('Upload image', id='upload-button')
           )
       ]),
       html.Div([
           html.Div(id='images-div'),
           html.Div(id='classification-div'),
           html.Div(id='classification-div2')
       ])
       ])
 ])

@app.callback(
   Output(component_id='images-div', component_property='children'),
   [Input('load-button','n_clicks')]
)
def update_output_div_img(n_clicks):
   return html.Div([html.Img(
                           src=app.get_asset_url(image),
                           style={
                                   'width' : '10%',
                                    'cursor': 'pointer'
                                   }
                       )], id='img'
                   )

@app.callback(
   Output(component_id='classification-div', component_property='children'),
   [Input('img','n_clicks')]
)
def update_output_div1(n_clicks):  
   return html.Div([html.H2('Div1')])

@app.callback(Output('classification-div2', 'children'),
             [Input('upload-data', 'contents')])
def update_output_div2(content):
   return html.Div([html.H2('Div2')])

@app.callback(
   Output(component_id='classification-div', component_property='style'),
   [Input('upload-data', 'contents')]
)
def update_style(content):
   if content:
       return {'display':'none'}
   else: return {'display':'inline'}


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

update_output_div_img загрузит изображение с обратным вызовом, когда вызагрузить страницу или при нажатии на кнопку «Загрузить изображение».Теперь после загрузки изображения вы можете щелкнуть по нему, и появится текст Div1.Когда вы нажимаете кнопку загрузки для загрузки изображения, «Div1» должен исчезнуть, и остается только Div 2.Пока все хорошо.

Теперь, когда я снова нажимаю на изображение, текст «Div1» не появляется, потому что дисплей был изменен на «нет».Я хочу, чтобы при повторном нажатии на изображение снова отображался текст «Div1», поэтому я изменил функцию обратного вызова для стиля первого элемента div, описанного выше, таким образом, чтобы он срабатывал при нажатии на изображение, и посколькусодержание, я думаю, должно изменить отображение на встроенное.

@app.callback(
   Output(component_id='classification-div', component_property='style'),
   [Input('upload-data', 'contents'),
    Input('img','n_clicks')]
)
def update_style(content,n_clicks):
   if content:
       return {'display':'none'}
   else: return {'display':'inline'}

Но это вызывает сообщение «Ошибка загрузки зависимостей» при загрузке веб-страницы.Я думаю, что проблема возникает, потому что изображение, по которому щелкают, генерируется другим обратным вызовом, в то время как компонент загрузки был загружен с самого начала.

Есть идеи, как обойти это?

1 Ответ

0 голосов
/ 05 марта 2019

Я не уверен, правильно ли я понял, что вы пытаетесь достичь, но вот исправление вашего кода, чтобы избежать проблемы с зависимостями:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
app = dash.Dash()
app.config['suppress_callback_exceptions']=True
image = "tmpimg.png"

app.layout = html.Div([
       html.Div([
       html.Div([
           html.Button('Load image', id='load-button'),
           dcc.Upload(
                   id='upload-data',
                   children=html.Button('Upload image', id='upload-button')
           )
       ]),
       html.Div([
           html.Div([html.Div(id='img')], id='images-div'),
           html.Div(id='classification-div'),
           html.Div(id='classification-div2')
       ])
       ])
 ])

@app.callback(
   Output(component_id='img', component_property='children'),
   [Input('load-button', 'n_clicks')]
)
def update_output_div_img(n_clicks):
    if n_clicks and n_clicks>0:
        return [html.Img(src=app.get_asset_url(image),
                               style={
                                       'width' : '10%',
                                        'cursor': 'pointer'
                                       })]

@app.callback(
   Output(component_id='classification-div', component_property='children'),
   [Input('img','n_clicks')]
)
def update_output_div1(n_clicks):
    if n_clicks and n_clicks>0:
        return [html.H2('Div1')]

@app.callback(Output('classification-div2', 'children'),
             [Input('upload-data', 'contents')])
def update_output_div2(content):
    if content:
        return [html.H2('Div2')]

@app.callback(
   Output(component_id='classification-div', component_property='style'),
   [Input('upload-data', 'contents'),
    Input('img','n_clicks')]
)
def update_style(content, n_clicks):
   if content and n_clicks and n_clicks>0:
       return {'display':'none'}
   else: return {'display':'inline'}


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

По сути, ваша проблема заключалась в том, что выпопытался использовать в качестве Входного компонента с id=img, который не определен в app.layout.Кроме того, рассмотрите возможность добавления проверок на n_clicks для всех кнопок, если вы не хотите, чтобы эти обратные вызовы запускались при загрузке страницы.

...