You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 13:40:47