Python PlotlyDash:刷新时有没有办法保持在同一位置?

2024-09-29 01:22:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在创建一个带有回调的设置选项卡,以便在用户切换按钮时显示选定的输入。但是,这意味着每次单击都会刷新页面,并且基本上会一直滚动到顶部,这对用户来说非常烦人。
(例如,如果您单击“自启动以来的总周数”滑块,它将刷新到顶部)

有什么方法可以在适当的地方刷新吗?我不希望使用滞后或去抖动功能来减慢刷新速度,因为这意味着输入不会立即反映给用户
(例如,我希望所选内容的即时输出显示在滑块上方)

谢谢大家!

要求的最低示例:

import argparse
import dash
import json
import dash_core_components as dcc
import dash_daq as daq
import dash_html_components as html
import dash_bootstrap_components as dbc
import pandas as pd
import webbrowser
from dash.dependencies import Input, State, Output

# Set up the app
app = dash.Dash(__name__, suppress_callback_exceptions=True)
app.title = 'Example App'
server = app.server
app_url = 'http://127.0.0.1:8050/'

# Define global variables
current_create_criteria_clicks = 0
outputs_path = 'outputs/'

# Define dropdown options
combined_criteria = []

# Define upload default text
upload_default_text = html.Div([
    'Drag and drop or ',
    html.A('select file')
])
# Define UI styles
input_area_style = {
    'width': '23%',
    'display': 'inline-block',
    'vertical-align': 'top',
    'font-family': 'Helvetica'
}
separator_area_style = {
    'width': '2%',
    'display': 'inline-block',
    'vertical-align': 'top',
    'font-family': 'Helvetica'
}
output_area_style = {
    'width': '75%',
    'display': 'inline-block',
    'vertical-align': 'top',
    'font-family': 'Helvetica'
}
left_output_area_style = {
    'width': '47%',
    'display': 'inline-block',
    'vertical-align': 'top'
}
right_output_area_style = {
    'width': '47%',
    'display': 'inline-block',
    'vertical-align': 'top',
    'font-family': 'Helvetica'
}
upload_box_style = {
    'width': '100%',
    'height': '60px',
    'lineHeight': '60px',
    'borderWidth': '1px',
    'borderStyle': 'dashed',
    'borderRadius': '10px',
    'textAlign': 'center',
    'margin': '0px',
    'font-family': 'Helvetica'
}
button_style = {
    'width': '50%',
    'height': '60px',
    'textAlign': 'center',
    'font-family': 'Helvetica'
}
center_placement_style = {
    'display': 'flex',
    'align-items': 'center',
    'justify-content': 'center',
    'font-family': 'Helvetica'
}

# Define hover_texts
text = {
    'settings-pX0-md-perc-text':
        [''],
    'settings-pX0-TotalWeekLaunch-text':
        ['If article was launched within or equals last N defined weeks, ',
         'there will be no movement for these SKUs x Stores.'],
    'settings-pX0-minmax-TotalWeekLaunch-text':
        [''],
    'settings-pX0-RptWeekLaunch-text':
        [''],
    'settings-pX0-minmax-RptWeekLaunch-text':
        [''],
    'settings-pX0-StoreCount-text':
        [''],
    'settings-pX0-minmax-StoreCount-text':
        [''],
    'settings-pX0-SOH-text':
        [''],
    'settings-pX0-minmax-SOH-text':
        [''],
    'settings-pX0-UTDSellThrough-perc-text':
        [''],
    'settings-pX0-minmax-UTDSellThrough-text':
        [''],
    'settings-pX0-ActualColorWeekTurnover-text':
        [''],
    'settings-pX0-minmax-ActualColorWeekTurnover-text':
        [''],
    'settings-pX0-TotalColorWeekTurnover-text':
        [''],
    'settings-pX0-minmax-TotalColorWeekTurnover-text':
        [''],
    'settings-pX0-CoreStatus-text':
        [''],
    'settings-pX0-BrokenStatus-text':
        [''],
    'settings-pX0-SKUGrade-text':
        [''],
    'settings-pX0-Seasonality-text':
        [''],
    'settings-pX0-Ideal-MD-ROS-text':
        [''],
    'settings-pX0-CombinedCriteria-text':
        ['']
}


def generate_hover_text(target_name):
    return dbc.Tooltip(
        text[target_name],
        target=target_name,
        placement='top-start',
        style={'width': '220pt',
               'line-height': '150%',
               'background-color': 'white',
               'font-family': 'Helvetica',
               'border': '2px solid #89CFF0',
               'border-radius': '5px',
               'padding-top': '5px',
               'padding-bottom': '5px',
               'padding-right': '5px',
               'padding-left': '10px'}
    )


def generate_default_settings(target_item, slider_max=50, slider_steps=1, mark_jumps=5):
    target_item_text = '-'.join(str(target_item).split('-')[:-1]) + '-text'
    target_item_area = '-'.join(str(target_item).split('-')[:-1]) + '-area'

    if 'booleanswitch' in target_item:
        display_unit = daq.BooleanSwitch(
            id=target_item,
            on=True
        )
    elif 'dropdown' in target_item:
        display_unit = dcc.Dropdown(
            id=target_item,
            multi=True
        )
    elif 'rangeslider' in target_item and ('proportion' in target_item or 'perc' in target_item):
        display_unit = dcc.RangeSlider(
            id=target_item,
            min=0,
            max=1,
            step=0.05,
            marks={value / 10: value / 10 for value in range(0, 10)}
        )
    elif 'rangeslider' in target_item:
        display_unit = dcc.RangeSlider(
            id=target_item,
            min=0,
            max=slider_max,
            step=slider_steps,
            marks={value * mark_jumps: value * mark_jumps for value in range(0, 10)}
        )
    elif ('slider' in target_item) and ('proportion' in target_item or 'perc' in target_item):
        display_unit = dcc.Slider(
            id=target_item,
            min=0,
            max=1,
            step=0.05,
            marks={value / 10: value / 10 for value in range(0, 10)}
        )
    elif 'slider' in target_item:
        display_unit = dcc.Slider(
            id=target_item,
            min=0,
            max=slider_max,
            step=slider_steps,
            marks={value * mark_jumps: value * mark_jumps for value in range(0, 10)}
        )

    return html.Div(
        id=target_item_area,
        children=[
            html.P(id=target_item_text),
            generate_hover_text(target_item_text),
            display_unit
        ]
    )


# Define app layout
app.layout = html.Div(
    id='app-body',
    children=[
        html.Div([
            html.H1('Example App')
        ], style={'text-align': 'left',
                  'margin-right': 20,
                  'display': 'inline-block',
                  'font-family': 'Helvetica'}),
        html.Div(
            id='tabs-area',
            children=[
                dcc.Tabs(
                    id='tabs',
                    children=[
                        dcc.Tab(
                            id='settings-tab',
                            label='Settings',
                            style={'font-family': 'Helvetica'},
                            children=[
                                html.Div(
                                    id='settings-output-area',
                                    children=[
                                        dcc.Loading(
                                            id='settings-output-loading',
                                            children=[
                                                html.Div(
                                                    id='left-separator-settings-output-area',
                                                    style=separator_area_style
                                                ),
                                                html.Div(
                                                    id='left-settings-output-area',
                                                    children=[],
                                                    style=left_output_area_style
                                                ),
                                                html.Div(
                                                    id='separator-settings-output-area',
                                                    style=separator_area_style
                                                ),
                                                html.Div(
                                                    id='right-settings-output-area',
                                                    children=[
                                                        html.H4('Criteria Creator'),
                                                        generate_default_settings('settings-pX0-md-perc-slider'),
                                                        generate_default_settings(
                                                            'settings-pX0-TotalWeekLaunch-slider'),
                                                        daq.BooleanSwitch(
                                                            id='settings-pX0-minmax-TotalWeekLaunch-booleanswitch'),
                                                        generate_default_settings('settings-pX0-RptWeekLaunch-slider'),
                                                        daq.BooleanSwitch(
                                                            id='settings-pX0-minmax-RptWeekLaunch-booleanswitch'),
                                                        generate_default_settings('settings-pX0-StoreCount-slider'),
                                                        daq.BooleanSwitch(
                                                            id='settings-pX0-minmax-StoreCount-booleanswitch'),
                                                        generate_default_settings(
                                                            'settings-pX0-SOH-slider',
                                                            slider_max=1000, slider_steps=5, mark_jumps=100
                                                        ),
                                                        daq.BooleanSwitch(id='settings-pX0-minmax-SOH-booleanswitch'),
                                                        generate_default_settings(
                                                            'settings-pX0-UTDSellThrough-perc-slider'),
                                                        daq.BooleanSwitch(
                                                            id='settings-pX0-minmax-UTDSellThrough-booleanswitch'),
                                                        generate_default_settings(
                                                            'settings-pX0-ActualColorWeekTurnover-slider',
                                                            slider_max=60, mark_jumps=6
                                                        ),
                                                        daq.BooleanSwitch(
                                                            id='settings-pX0-minmax-ActualColorWeekTurnover-booleanswitch'
                                                        ),
                                                        generate_default_settings(
                                                            'settings-pX0-TotalColorWeekTurnover-slider',
                                                            slider_max=60, mark_jumps=6
                                                        ),
                                                        daq.BooleanSwitch(
                                                            id='settings-pX0-minmax-TotalColorWeekTurnover-booleanswitch'
                                                        ),
                                                        generate_default_settings('settings-pX0-CoreStatus-dropdown'),
                                                        generate_default_settings('settings-pX0-BrokenStatus-dropdown'),
                                                        generate_default_settings('settings-pX0-SKUGrade-dropdown'),
                                                        generate_default_settings('settings-pX0-Seasonality-dropdown'),
                                                        generate_default_settings('settings-pX0-Ideal-MD-ROS-dropdown'),
                                                        html.Button(
                                                            id='settings-pX0-create-criteria-button',
                                                            n_clicks=0,
                                                            children='Create Criteria',
                                                            style=button_style
                                                        ),
                                                        html.Button(
                                                            id='settings-pX0-clear-criteria-button',
                                                            n_clicks=0,
                                                            children='Reset Criteria',
                                                            style=button_style
                                                        ),
                                                        html.H4('MD Criteria Selector'),
                                                        generate_default_settings(
                                                            'settings-pX0-CombinedCriteria-dropdown')
                                                    ],
                                                    style=right_output_area_style
                                                ),
                                                html.Div(
                                                    id='right-separator-settings-output-area',
                                                    style=separator_area_style
                                                )
                                            ],
                                            type='circle',
                                            style={'vertical-align': 'middle'}
                                        )
                                    ],
                                    style=output_area_style
                                ),
                                html.P(id='settings-placeholder')
                            ]
                        )
                    ]
                )
            ]
        )
    ]
)

@app.callback(
    [
        Output('settings-pX0-md-perc-text', 'children'),
        Output('settings-pX0-TotalWeekLaunch-text', 'children'),
        Output('settings-pX0-RptWeekLaunch-text', 'children'),
        Output('settings-pX0-StoreCount-text', 'children'),
        Output('settings-pX0-SOH-text', 'children'),
        Output('settings-pX0-UTDSellThrough-perc-text', 'children'),
        Output('settings-pX0-ActualColorWeekTurnover-text', 'children'),
        Output('settings-pX0-TotalColorWeekTurnover-text', 'children'),
        Output('settings-pX0-CoreStatus-text', 'children'),
        Output('settings-pX0-BrokenStatus-text', 'children'),
        Output('settings-pX0-SKUGrade-text', 'children'),
        Output('settings-pX0-Seasonality-text', 'children'),
        Output('settings-pX0-Ideal-MD-ROS-text', 'children'),
        Output('settings-pX0-CombinedCriteria-dropdown', 'options')
    ],
    [
        Input('settings-pX0-create-criteria-button', 'n_clicks'),
        Input('settings-pX0-md-perc-slider', 'value'),
        Input('settings-pX0-TotalWeekLaunch-slider', 'value'),
        Input('settings-pX0-minmax-TotalWeekLaunch-booleanswitch', 'on'),
        Input('settings-pX0-RptWeekLaunch-slider', 'value'),
        Input('settings-pX0-minmax-RptWeekLaunch-booleanswitch', 'on'),
        Input('settings-pX0-StoreCount-slider', 'value'),
        Input('settings-pX0-minmax-StoreCount-booleanswitch', 'on'),
        Input('settings-pX0-SOH-slider', 'value'),
        Input('settings-pX0-minmax-SOH-booleanswitch', 'on'),
        Input('settings-pX0-UTDSellThrough-perc-slider', 'value'),
        Input('settings-pX0-minmax-UTDSellThrough-booleanswitch', 'on'),
        Input('settings-pX0-ActualColorWeekTurnover-slider', 'value'),
        Input('settings-pX0-minmax-ActualColorWeekTurnover-booleanswitch', 'on'),
        Input('settings-pX0-TotalColorWeekTurnover-slider', 'value'),
        Input('settings-pX0-minmax-TotalColorWeekTurnover-booleanswitch', 'on'),
        Input('settings-pX0-CoreStatus-dropdown', 'value'),
        Input('settings-pX0-BrokenStatus-dropdown', 'value'),
        Input('settings-pX0-SKUGrade-dropdown', 'value'),
        Input('settings-pX0-Seasonality-dropdown', 'value'),
        Input('settings-pX0-Ideal-MD-ROS-dropdown', 'value')
    ]
)
def update_criteria_dropdown(pX0_create_criteria_clicks, pX0_md_perc, pX0_TotalWeekLaunch,
                             pX0_minmax_TotalWeekLaunch,
                             pX0_RptWeekLaunch, pX0_minmax_RptWeekLaunch, pX0_StoreCount, pX0_minmax_StoreCount,
                             pX0_SOH, pX0_minmax_SOH, pX0_UTDSellThrough, pX0_minmax_UTDSellThrough,
                             pX0_ActualColorWeekTurnover, pX0_minmax_ActualColorWeekTurnover,
                             pX0_TotalColorWeekTurnover, pX0_minmax_TotalColorWeekTurnover, pX0_CoreStatus,
                             pX0_BrokenStatus, pX0_SKUGrade, pX0_Seasonality, pX0_IdealMDROS):
    global current_create_criteria_clicks
    global combined_criteria

    pX0_md_perc_text = 'Proposed Additional MD %'
    pX0_TotalWeekLaunch_text = 'Number of Launch Weeks'
    pX0_RptWeekLaunch_text = 'Number of Rpt Launch Weeks'
    pX0_StoreCount_text = 'Number of Stores Holding'
    pX0_SOH_text = 'Total SOH Qty'
    pX0_UTDSellThrough_text = 'UTD SellThrough %'
    pX0_ActualColorWeekTurnover_text = 'Current WeekTurn'
    pX0_TotalColorWeekTurnover_text = 'Total WeekTurn since Launch'
    pX0_CoreStatus_text = 'Apply to selected Core Status'
    pX0_BrokenStatus_text = 'Apply to selected Broken Status'
    pX0_SKUGrade_text = 'Apply to selected ABC Grade'
    pX0_Seasonality_text = 'Apply to selected Seasonality'
    pX0_IdealMDROS_text = 'Apply to selected Ideal LastMD ROS Status'

    # update combined_criteria
    def tf_more_less(boo):
        return 'min >=' if boo else 'max <='
        # return 'Largest to Smallest' if boo else 'Smallest to Largest'

    criteria_dict = {}
    if pX0_md_perc is not None:
        pX0_md_perc_text += ': %d ' % (pX0_md_perc * 100) + '%'
        criteria_dict['MD_Req'] = pX0_md_perc
    if None not in (pX0_TotalWeekLaunch, pX0_minmax_TotalWeekLaunch):
        pX0_TotalWeekLaunch_text += ': ' + tf_more_less(pX0_minmax_TotalWeekLaunch) + '%d' % pX0_TotalWeekLaunch
        criteria_dict['TotalWeekLaunch'] = {}
        criteria_dict['TotalWeekLaunch']['value'] = pX0_TotalWeekLaunch
        criteria_dict['TotalWeekLaunch']['min'] = pX0_minmax_TotalWeekLaunch
    if None not in (pX0_RptWeekLaunch, pX0_minmax_RptWeekLaunch):
        pX0_RptWeekLaunch_text += ': ' + tf_more_less(pX0_minmax_RptWeekLaunch) + '%d' % pX0_RptWeekLaunch
        criteria_dict['RptWeekLaunch'] = {}
        criteria_dict['RptWeekLaunch']['value'] = pX0_RptWeekLaunch
        criteria_dict['RptWeekLaunch']['min'] = pX0_minmax_RptWeekLaunch
    if None not in (pX0_StoreCount, pX0_minmax_StoreCount):
        pX0_StoreCount_text += ': ' + tf_more_less(pX0_minmax_StoreCount) + '%d' % pX0_StoreCount
        criteria_dict['StoreCount'] = {}
        criteria_dict['StoreCount']['value'] = pX0_StoreCount
        criteria_dict['StoreCount']['min'] = pX0_minmax_StoreCount
    if None not in (pX0_SOH, pX0_minmax_SOH):
        pX0_SOH_text += ': ' + tf_more_less(pX0_minmax_SOH) + '%d' % pX0_SOH
        criteria_dict['SOH'] = {}
        criteria_dict['SOH']['value'] = pX0_SOH
        criteria_dict['SOH']['min'] = pX0_minmax_SOH
    if None not in (pX0_UTDSellThrough, pX0_minmax_UTDSellThrough):
        pX0_UTDSellThrough_text += ': ' + tf_more_less(pX0_minmax_UTDSellThrough) + '%d' % (
                    pX0_UTDSellThrough * 100) + '%'
        criteria_dict['UTDSellThrough'] = {}
        criteria_dict['UTDSellThrough']['value'] = pX0_UTDSellThrough
        criteria_dict['UTDSellThrough']['min'] = pX0_minmax_UTDSellThrough
    if None not in (pX0_ActualColorWeekTurnover, pX0_minmax_ActualColorWeekTurnover):
        pX0_ActualColorWeekTurnover_text += ': ' + tf_more_less(
            pX0_minmax_ActualColorWeekTurnover) + '%d' % pX0_ActualColorWeekTurnover
        criteria_dict['ActualColorWeekTurnover'] = {}
        criteria_dict['ActualColorWeekTurnover']['value'] = pX0_ActualColorWeekTurnover
        criteria_dict['ActualColorWeekTurnover']['min'] = pX0_minmax_ActualColorWeekTurnover
    if None not in (pX0_TotalColorWeekTurnover, pX0_minmax_TotalColorWeekTurnover):
        pX0_TotalColorWeekTurnover_text += ': ' + tf_more_less(
            pX0_minmax_TotalColorWeekTurnover) + '%d' % pX0_TotalColorWeekTurnover
        criteria_dict['TotalColorWeekTurnover'] = {}
        criteria_dict['TotalColorWeekTurnover']['value'] = pX0_TotalColorWeekTurnover
        criteria_dict['TotalColorWeekTurnover']['min'] = pX0_minmax_TotalColorWeekTurnover
    if pX0_CoreStatus is not None:
        if len(pX0_CoreStatus) > 0:
            criteria_dict['CoreStatus'] = pX0_CoreStatus
    if pX0_BrokenStatus is not None:
        if len(pX0_BrokenStatus) > 0:
            criteria_dict['BrokenStatus'] = pX0_BrokenStatus
    if pX0_SKUGrade is not None:
        if len(pX0_SKUGrade) > 0:
            criteria_dict['SKUGrade'] = pX0_SKUGrade
    if pX0_Seasonality is not None:
        if len(pX0_Seasonality) > 0:
            criteria_dict['Seasonality'] = pX0_Seasonality
    if pX0_IdealMDROS is not None:
        if len(pX0_IdealMDROS) > 0:
            criteria_dict['LastMDROSStatus'] = pX0_IdealMDROS

    if pX0_create_criteria_clicks is not None and pX0_create_criteria_clicks > 0 \
            and pX0_create_criteria_clicks > current_create_criteria_clicks \
            and 'MD_Req' in criteria_dict.keys() and len(criteria_dict) > 1:
        current_create_criteria_clicks = pX0_create_criteria_clicks
        combined_criteria.append(json.dumps(criteria_dict))

    crits = [{'label': crit, 'value': crit} for crit in combined_criteria]

    return pX0_md_perc_text, pX0_TotalWeekLaunch_text, pX0_RptWeekLaunch_text, pX0_StoreCount_text, pX0_SOH_text, \
           pX0_UTDSellThrough_text, pX0_ActualColorWeekTurnover_text, pX0_TotalColorWeekTurnover_text, \
           pX0_CoreStatus_text, pX0_BrokenStatus_text, pX0_SKUGrade_text, pX0_Seasonality_text, pX0_IdealMDROS_text, crits

@app.callback(
    [
        Output('settings-pX0-md-perc-slider', 'value'),
        Output('settings-pX0-TotalWeekLaunch-slider', 'value'),
        Output('settings-pX0-minmax-TotalWeekLaunch-booleanswitch', 'on'),
        Output('settings-pX0-RptWeekLaunch-slider', 'value'),
        Output('settings-pX0-minmax-RptWeekLaunch-booleanswitch', 'on'),
        Output('settings-pX0-StoreCount-slider', 'value'),
        Output('settings-pX0-minmax-StoreCount-booleanswitch', 'on'),
        Output('settings-pX0-SOH-slider', 'value'),
        Output('settings-pX0-minmax-SOH-booleanswitch', 'on'),
        Output('settings-pX0-UTDSellThrough-perc-slider', 'value'),
        Output('settings-pX0-minmax-UTDSellThrough-booleanswitch', 'on'),
        Output('settings-pX0-ActualColorWeekTurnover-slider', 'value'),
        Output('settings-pX0-minmax-ActualColorWeekTurnover-booleanswitch', 'on'),
        Output('settings-pX0-TotalColorWeekTurnover-slider', 'value'),
        Output('settings-pX0-minmax-TotalColorWeekTurnover-booleanswitch', 'on'),
        Output('settings-pX0-CoreStatus-dropdown', 'value'),
        Output('settings-pX0-BrokenStatus-dropdown', 'value'),
        Output('settings-pX0-SKUGrade-dropdown', 'value'),
        Output('settings-pX0-Seasonality-dropdown', 'value'),
        Output('settings-pX0-Ideal-MD-ROS-dropdown', 'value')
    ],
    [
        Input('settings-pX0-clear-criteria-button', 'n_clicks')
    ]
)
def clear_criteria(clear_criteria_clicks):
    return None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, \
           [], [], [], [], []



# Run the Dash app server
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Example App')
    parser.add_argument('--debug', help='Run the app in debug mode', action='store_true')
    arguments = parser.parse_args()
    webbrowser.open(app_url)
    # Run the Dash server
    app.run_server(debug=arguments.debug)

Tags: textnoneidtargetoutputsettingsvaluestyle
1条回答
网友
1楼 · 发布于 2024-09-29 01:22:45

您可以使用官方文档中的这个dcc.tabs示例。这将帮助您避免在更改选项卡时刷新

app.layout = html.Div([
    dcc.Tabs(id='tabs-example', value='tab-1', children=[
        dcc.Tab(label='Tab one', value='tab-1'),
        dcc.Tab(label='Tab two', value='tab-2'),
    ]),
    html.Div(id='tabs-example-content')
])

@app.callback(Output('tabs-example-content', 'children'),
              [Input('tabs-example', 'value')])
def render_content(tab):
    if tab == 'tab-1':
        return html.Div([
            html.H3('Tab content 1')
        ])
    elif tab == 'tab-2':
        return html.Div([
            html.H3('Tab content 2')
        ])

您可以通过将选项卡的内容像事件一样单独存储,或者从不同的文件导入,来进一步扩展这个想法

   tab1_layout = [ html.Div([ dcc.Graph … etc ]) ]
   tab2_content = [ html.Div([ dcc.Graph … etc ]) ]

相关问题 更多 >