Mathematica中InputField触发长计算时如何动态更新ProgressIndicator
问题原因
InputField的自定义赋值回调属于同步执行逻辑,回调函数完整运行结束前,Mathematica前端会暂停所有UI动态刷新操作,因此你在回调开头修改的updatingQ=True状态,不会被外层的Dynamic捕获渲染,等2秒计算完成后updatingQ已经被重置为False,自然看不到进度提示。
Button的Method->"Queued"本质是把点击回调逻辑提交到后台任务队列,主线程会立刻返回处理UI刷新,所以进度提示可以正常展示,InputField没有自带该参数,我们可以手动通过后台任务实现相同效果。
可行实现代码
Clear[ProgressIndicatorTest] ProgressIndicatorTest = { TextCell["ProgressIndicatorTest", "Subsubsection", Background -> LightBlue], DynamicModule[ {filterTypes = {"Max energy", "Max length"}, filterValue, workingOn = "", iter = 0, updatingQ = False}, Scan[(filterValue[#[[1]]] = #[[2]]) &, Transpose@{filterTypes, {0.1, 100.}}]; Dynamic[ Grid[ Join[ Map[ Function[ filterType, {filterType, Dynamic@ InputField[ Dynamic[ filterValue[filterType], Function[value, If[value > 0, (* 立刻修改状态并提交任务到后台,回调直接返回不阻塞 *) updatingQ = True; SessionSubmit[ Task[ (* 执行耗时计算 *) Pause[2]; filterValue[filterType] = π value; updatingQ = False; ] ]; ] ] ], FieldSize -> 5, Alignment -> Right ] } ], filterTypes ], {{updatingQ, "-------"}}, {If[updatingQ, {"Updating ... ", ProgressIndicator[Appearance -> "Indeterminate"]}, Nothing ]} ], Alignment -> Left, Background -> {None, {LightGreen, LightGreen, LightYellow, LightYellow}} ] ] ] }; CellGroup[ProgressIndicatorTest]
如果你使用的是Mathematica 11以前的版本,可以将
SessionSubmit替换为CreateScheduledTask[..., {0}]实现相同的后台提交效果。
关键修改说明
- 把全局变量
updatingQ移入DynamicModule内部,避免多实例状态冲突 - 赋值回调中仅做状态修改和任务提交操作,立刻释放前端线程处理UI刷新,
updatingQ=True的状态会立刻被外层Dynamic捕获,渲染出进度提示 - 耗时计算逻辑全部放在
SessionSubmit提交的后台任务中执行,执行完成后自动更新数值并重置进度状态
内容的提问来源于stack exchange,提问作者jjoIV
相关产品推荐
相关产品推荐

