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

如何为Holoviz Panel添加计算过程中的加载指示器?

在Holoviz Panel中实现加载指示器的方案

你的问题核心在于同步执行耗时计算会阻塞UI线程,导致加载状态无法正常更新,哪怕给按钮加loading_indicator=True也没用。下面给出两种可行的实现方式,都是通过异步/后台线程处理计算,同时显示加载动画:

方法一:使用线程+LoadingSpinner组件

这种方式适合大多数场景,把耗时计算放到后台线程,避免阻塞UI:

import panel as pn
import pandas as pd
import time
import threading

pn.extension()

# 创建加载指示器,初始隐藏
loading_spinner = pn.indicators.LoadingSpinner(value=False, size=50, name="计算中...")

submit_button = pn.widgets.Button(name='Submit', button_type='primary', width=180)
radio_buttons_group = pn.widgets.RadioButtonGroup(options=['Ying', 'Yang'], button_type='default')
outer_col = pn.Column(radio_buttons_group, submit_button, loading_spinner)

def handle_calculation(selected_value):
    # 模拟耗时计算
    time.sleep(3)
    
    # 计算完成后更新UI:隐藏加载器,显示结果
    loading_spinner.value = False
    if len(outer_col) > 3:
        outer_col.pop(len(outer_col)-1)
    
    if selected_value == 'Ying':
        outer_col.append(pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]}))
    else:
        outer_col.append(pd.DataFrame({'col1': [5, 6], 'col2': [7, 8]}))

@pn.depends(submit_button.param.clicks, watch=True)
def display_result(event):
    # 点击按钮后先显示加载器
    loading_spinner.value = True
    
    # 移除之前的结果(如果存在)
    if len(outer_col) > 3:
        outer_col.pop(len(outer_col)-1)
    
    # 启动后台线程处理计算
    selected_val = radio_buttons_group.value
    threading.Thread(target=handle_calculation, args=(selected_val,), daemon=True).start()

outer_col

方法二:使用Panel的异步装饰器(更简洁)

Panel支持用@pn.asynchronous装饰异步函数,配合asyncio实现无阻塞计算:

import panel as pn
import pandas as pd
import time
import asyncio

pn.extension()

loading_spinner = pn.indicators.LoadingSpinner(value=False, size=50, name="计算中...")

submit_button = pn.widgets.Button(name='Submit', button_type='primary', width=180)
radio_buttons_group = pn.widgets.RadioButtonGroup(options=['Ying', 'Yang'], button_type='default')
outer_col = pn.Column(radio_buttons_group, submit_button, loading_spinner)

@pn.asynchronous
async def async_calculation(selected_value):
    loading_spinner.value = True
    await asyncio.sleep(3)  # 模拟耗时计算
    
    if selected_value == 'Ying':
        result = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})
    else:
        result = pd.DataFrame({'col1': [5, 6], 'col2': [7, 8]})
    
    loading_spinner.value = False
    return result

@pn.depends(submit_button.param.clicks, watch=True)
def display_result(event):
    if len(outer_col) > 3:
        outer_col.pop(len(outer_col)-1)
    
    selected_val = radio_buttons_group.value
    # 调用异步计算并将结果添加到面板
    result = async_calculation(selected_val)
    outer_col.append(result)

outer_col

为什么loading_indicator=True没效果?

Button的loading_indicator=True是让按钮自身显示加载状态,但如果你的计算是同步执行的,整个Panel的UI线程会被阻塞,按钮的加载动画根本来不及渲染。必须把耗时计算放到后台线程或异步任务中,让UI线程能同时更新加载状态。

内容的提问来源于stack exchange,提问作者argcv

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:00:59