You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在Gradio应用的每个标签页中显示专属进度条

如何在Gradio应用的每个标签页中显示专属进度条

我明白你现在的困扰:全局触发所有模型生成时,所有标签页都同步显示同一个进度条,完全分不清哪个模型在运行、跑了多少进度。咱们来一步步解决这个问题,核心是让每个标签页的进度条和对应模型的生成逻辑精准绑定,互不干扰。

问题根源

你当前的代码里,虽然给每个标签页都加了gr.Progress组件,但有两个关键问题:

  1. 这些进度条组件没有被加入生成函数的输出列表,直接调用progress_dict[model_name](...)只会触发全局临时进度条,导致所有标签页同步显示。
  2. 单个generate_all函数同时处理所有模型,进度更新没有和对应标签页的组件做精准绑定。

解决方案一:保留全局生成按钮,实现标签专属进度条

这个方案适配你原来的全局Generate按钮逻辑,让每个模型的进度只在自己的标签页显示:

1. 调整UI结构,明确组件绑定

首先,在每个标签页里把进度条、图片、种子组件归为一组,然后把所有进度条加入输出组件列表:

with gr.Blocks(css=css) as demo:
    with gr.Column(elem_id="col-container"):
        gr.Markdown("# Multi-Model Image Generation")

        # 全局输入参数
        with gr.Row():
            prompt = gr.Text(
                label="Prompt",
                show_label=False,
                max_lines=1,
                placeholder="Enter your prompt",
                container=False,
            )
            run_button = gr.Button("Generate", scale=0, variant="primary")

        with gr.Accordion("Advanced Settings", open=False):
            seed = gr.Slider(
                label="Seed",
                minimum=0,
                maximum=100000,
                step=1,
                value=0,
            )
            randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
            width = gr.Slider(label="Width", minimum=512, maximum=MAX_IMAGE_SIZE, step=64, value=1024)
            height = gr.Slider(label="Height", minimum=512, maximum=MAX_IMAGE_SIZE, step=64, value=1024)
            guidance_scale = gr.Slider(label="Guidance Scale", minimum=1, maximum=20, step=0.5, value=7.5)
            num_inference_steps = gr.Slider(label="Inference Steps", minimum=10, maximum=100, step=1, value=30)
            negative_prompt = gr.Text(label="Negative Prompt", placeholder="Enter negative prompt")

        memory_indicator = gr.Markdown("Current memory usage: 0 GB")

        # 标签页区域
        with gr.Row():
            with gr.Column(scale=2):
                with gr.Tabs() as tabs:
                    results = {}
                    seeds = {}
                    progress_dict: dict[str, gr.Progress] = {}

                    for model_name in MODEL_CONFIGS.keys():
                        with gr.Tab(model_name):
                            # 每个标签页内用Column分组组件,逻辑更清晰
                            with gr.Column():
                                results[model_name] = gr.Image(label=f"{model_name} Result")
                                seeds[model_name] = gr.Number(label="Seed used", visible=True)
                                # 每个标签专属的进度条
                                progress_dict[model_name] = gr.Progress()

        # 准备输入输出组件:每个模型对应【图片、种子、进度条】三个输出
        input_components = [
            prompt, negative_prompt, seed, randomize_seed, width, height,
            guidance_scale, num_inference_steps
        ]
        output_components = []
        for model_name in MODEL_CONFIGS.keys():
            output_components.extend([results[model_name], seeds[model_name], progress_dict[model_name]])

        run_button.click(
            fn=generate_all,
            inputs=input_components,
            outputs=output_components,
        )

2. 重构生成函数,精准更新对应进度条

修改generate_all函数,用gr.Progress.update()来传递进度状态,确保每个模型的进度只更新自己标签页的组件:

def generate_all(prompt, negative_prompt, seed, randomize_seed, width, height,
                 guidance_scale, num_inference_steps):
    # 初始化所有输出:每个模型的【图片、种子、进度条】,进度条默认显示等待状态
    all_outputs = []
    for model_name in MODEL_CONFIGS.keys():
        all_outputs.extend([
            None,  # 初始图片为空
            None,  # 初始种子为空
            gr.Progress.update(value=0, desc=f"等待生成 {model_name}...")
        ])
    yield all_outputs  # 先返回初始状态

    for idx, model_name in enumerate(MODEL_CONFIGS.keys()):
        try:
            # 计算当前模型在输出列表中的起始索引(每个模型占3个输出位)
            base_idx = idx * 3
            # 1. 更新当前模型的进度条为开始状态
            all_outputs[base_idx + 2] = gr.Progress.update(
                value=0, 
                desc=f"开始生成 {model_name}..."
            )
            yield all_outputs

            generated_seed = seed if not randomize_seed else random.randint(0, 100000)
            print(f"正在生成 {model_name}")

            # 2. 模拟生成过程,分步更新进度(替换为实际模型推理逻辑)
            total_steps = num_inference_steps
            for step in range(total_steps):
                sleep(0.05)  # 模拟推理耗时
                progress = (step + 1) / total_steps
                all_outputs[base_idx + 2] = gr.Progress.update(
                    value=progress, 
                    desc=f"{model_name} 生成中: {int(progress*100)}%"
                )
                yield all_outputs

            # 3. 模拟获取生成的图片(替换为实际模型推理代码)
            url = f"https://placehold.co/{width}x{height}/000000/FFFFFF.png?text={model_name.replace(' ','+')}+{generated_seed}"
            image = fetch_image_from_url(url)

            # 4. 更新最终结果:图片、种子,进度条标记完成
            all_outputs[base_idx] = image
            all_outputs[base_idx + 1] = generated_seed
            all_outputs[base_idx + 2] = gr.Progress.update(
                value=1, 
                desc=f"{model_name} 生成完成!"
            )
            yield all_outputs

        except Exception as e:
            print(f"{model_name} 生成出错: {str(e)}")
            base_idx = idx *3
            all_outputs[base_idx +2] = gr.Progress.update(
                value=1, 
                desc=f"{model_name} 生成失败!"
            )
            yield all_outputs

    return all_outputs

解决方案二:每个标签页独立触发生成(更推荐)

如果可以接受每个标签页有自己的生成按钮,这个方案更简洁,进度条完全独立,不会有任何干扰:

1. 编写通用单模型生成函数

def generate_single(model_name, prompt, negative_prompt, seed, randomize_seed, width, height,
                    guidance_scale, num_inference_steps):
    # 用gr.Progress上下文,进度条会自动绑定到当前触发的标签页
    with gr.Progress() as progress:
        progress(0, desc=f"初始化 {model_name}...")
        generated_seed = seed if not randomize_seed else random.randint(0, 100000)
        
        total_steps = num_inference_steps
        for step in range(total_steps):
            sleep(0.05)
            progress((step+1)/total_steps, desc=f"{model_name} 生成中: {int((step+1)/total_steps*100)}%")
        
        # 替换为实际模型推理代码
        url = f"https://placehold.co/{width}x{height}/000000/FFFFFF.png?text={model_name.replace(' ','+')}+{generated_seed}"
        image = fetch_image_from_url(url)
        
        progress(1, desc=f"{model_name} 生成完成!")
        return image, generated_seed

2. 调整UI,每个标签页添加独立生成按钮

with gr.Blocks(css=css) as demo:
    with gr.Column(elem_id="col-container"):
        gr.Markdown("# Multi-Model Image Generation")

        # 全局参数面板
        with gr.Row():
            prompt = gr.Text(
                label="Prompt",
                show_label=False,
                max_lines=1,
                placeholder="Enter your prompt",
                container=False,
            )

        with gr.Accordion("Advanced Settings", open=False):
            seed = gr.Slider(
                label="Seed",
                minimum=0,
                maximum=100000,
                step=1,
                value=0,
            )
            randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
            width = gr.Slider(label="Width", minimum=512, maximum=MAX_IMAGE_SIZE, step=64, value=1024)
            height = gr.Slider(label="Height", minimum=512, maximum=MAX_IMAGE_SIZE, step=64, value=1024)
            guidance_scale = gr.Slider(label="Guidance Scale", minimum=1, maximum=20, step=0.5, value=7.5)
            num_inference_steps = gr.Slider(label="Inference Steps", minimum=10, maximum=100, step=1, value=30)
            negative_prompt = gr.Text(label="Negative Prompt", placeholder="Enter negative prompt")

        memory_indicator = gr.Markdown("Current memory usage: 0 GB")

        # 标签页区域
        with gr.Row():
            with gr.Column(scale=2):
                with gr.Tabs() as tabs:
                    results = {}
                    seeds = {}

                    for model_name in MODEL_CONFIGS.keys():
                        with gr.Tab(model_name):
                            with gr.Column():
                                results[model_name] = gr.Image(label=f"{model_name} Result")
                                seeds[model_name] = gr.Number(label="Seed used", visible=True)
                                # 每个标签页的独立生成按钮
                                gen_btn = gr.Button(f"生成 {model_name}")
                                # 绑定生成函数
                                gen_btn.click(
                                    fn=generate_single,
                                    inputs=[
                                        gr.State(model_name),  # 传递当前模型名称
                                        prompt, negative_prompt, seed, randomize_seed,
                                        width, height, guidance_scale, num_inference_steps
                                    ],
                                    outputs=[results[model_name], seeds[model_name]]
                                )

这个方案里,每个标签页的生成按钮触发独立的函数,gr.Progress上下文会自动在当前标签页显示进度,完全不会影响其他标签,体验更清晰。

最后验证

修改后你点击生成时,每个标签页的进度条只会显示对应模型的生成状态,比如FLUX的进度只会在FLUX标签页出现,PixArt的进度只在自己的标签页运行,终于能清晰区分每个模型的状态啦!

备注:内容来源于stack exchange,提问作者RagAnt

火山引擎 最新活动