Plotly Dash数字键盘输入四位数字报错问题求助
Plotly Dash数字键盘输入四位数字功能修复
问题背景
用户尝试实现四位数字的键盘输入功能:点击数字按钮时,输出区域拼接对应数字(如点击2显示2,再点击3显示23),但运行代码时抛出KeyError: 'output.children'错误,无法获取输出区域的历史状态完成数字拼接。
用户原始代码:
import dash import dash_daq as daq import dash_html_components as html from dash.dependencies import Input, Output app = dash.Dash() app.layout = html.Div([ html.Div([ html.Button(id='button-7', value='7', children='7', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-8', value='8', children='8', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-9', value='9', children='9', style={'fontSize':24, 'width': '33%', 'height': '60px'}) ], style={'display': 'flex'}), html.Div([ html.Button(id='button-4', value='4', children='4', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-5', value='5', children='5', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-6', value='6', children='6', style={'fontSize':24, 'width': '33%', 'height': '60px'}) ], style={'display': 'flex'}), html.Div([ html.Button(id='button-1', value='1', children='1', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-2', value='2', children='2', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-3', value='3', children='3', style={'fontSize':24, 'width': '33%', 'height': '60px'}) ], style={'display': 'flex'}), html.Div([ html.Button(id='button-0', value='0', children='0', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button('Reset', id='button-reset', style={'fontSize':24, 'width': '33%', 'height': '60px'}), ], style={'display': 'flex'}), html.Div([ html.Output(id='output', children='', style={'fontSize':48, 'width': '100%', 'height': '60px'}) ], style={'display': 'flex'}) ]) @app.callback( Output('output', 'children'), [Input('button-1', 'n_clicks'), Input('button-2', 'n_clicks'), Input('button-3', 'n_clicks'), Input('button-4', 'n_clicks'), Input('button-5', 'n_clicks'), Input('button-6', 'n_clicks'), Input('button-7', 'n_clicks'), Input('button-8', 'n_clicks'), Input('button-9', 'n_clicks'), Input('button-0', 'n_clicks'), State('output', 'children')]) def display_output(*n_clicks): ctx = dash.callback_context if not ctx.triggered: return '' else: button_id = ctx.triggered[0]['prop_id'].split('.')[0] button_value = button_id.split('-')[-1] output_value = ctx.inputs['output.children'] + button_value if len(ctx.inputs['output.children']) < 4 else ctx.inputs['output.children'] return output_value if __name__ == '__main__': app.run_server()
错误信息
output_value = ctx.inputs['output.children'] + button_value if len(ctx.inputs['output.children']) < 4 else ctx.inputs['output.children'] KeyError: 'output.children'
问题原因
ctx.inputs仅包含Input类型的参数,而output.children是通过State传入的,不在ctx.inputs范围内,因此触发KeyError。同时原始代码未处理Reset按钮的清空逻辑。
修复方案
直接使用回调函数的参数获取output.children的历史状态,补充Reset按钮逻辑,优化按钮值的获取方式:
修复后的代码:
import dash import dash_html_components as html from dash.dependencies import Input, Output, State app = dash.Dash() app.layout = html.Div([ html.Div([ html.Button(id='button-7', value='7', children='7', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-8', value='8', children='8', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-9', value='9', children='9', style={'fontSize':24, 'width': '33%', 'height': '60px'}) ], style={'display': 'flex'}), html.Div([ html.Button(id='button-4', value='4', children='4', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-5', value='5', children='5', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-6', value='6', children='6', style={'fontSize':24, 'width': '33%', 'height': '60px'}) ], style={'display': 'flex'}), html.Div([ html.Button(id='button-1', value='1', children='1', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-2', value='2', children='2', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button(id='button-3', value='3', children='3', style={'fontSize':24, 'width': '33%', 'height': '60px'}) ], style={'display': 'flex'}), html.Div([ html.Button(id='button-0', value='0', children='0', style={'fontSize':24, 'width': '33%', 'height': '60px'}), html.Button('Reset', id='button-reset', value='reset', style={'fontSize':24, 'width': '33%', 'height': '60px'}), ], style={'display': 'flex'}), html.Div([ html.Output(id='output', children='', style={'fontSize':48, 'width': '100%', 'height': '60px', 'textAlign': 'center'}) ], style={'display': 'flex', 'justifyContent': 'center', 'marginTop': '20px'}) ]) @app.callback( Output('output', 'children'), [Input('button-1', 'n_clicks'), Input('button-2', 'n_clicks'), Input('button-3', 'n_clicks'), Input('button-4', 'n_clicks'), Input('button-5', 'n_clicks'), Input('button-6', 'n_clicks'), Input('button-7', 'n_clicks'), Input('button-8', 'n_clicks'), Input('button-9', 'n_clicks'), Input('button-0', 'n_clicks'), Input('button-reset', 'n_clicks')], [State('output', 'children')]) def display_output(*args): ctx = dash.callback_context if not ctx.triggered: return '' button_id = ctx.triggered[0]['prop_id'].split('.')[0] current_output = args[-1] if button_id == 'button-reset': return '' # 通过布局结构获取按钮的value属性 btn_idx = int(button_id.split('-')[1]) row_idx = btn_idx // 3 col_idx = btn_idx % 3 button_value = app.layout.children[row_idx].children[col_idx].value if len(current_output) < 4: return current_output + button_value else: return current_output if __name__ == '__main__': app.run_server(debug=True)
关键修复点
- 直接使用回调函数的最后一个参数(State传入的历史状态)获取
output.children,不再依赖ctx.inputs - 新增Reset按钮的清空逻辑
- 通过布局结构直接获取按钮的
value属性,避免从ID拆分可能出现的错误 - 优化输出区域样式,让数字居中显示
内容的提问来源于stack exchange,提问作者bryantjaimer
相关产品推荐
相关产品推荐

