如何在Gradio应用的每个标签页中显示专属进度条
如何在Gradio应用的每个标签页中显示专属进度条
我明白你现在的困扰:全局触发所有模型生成时,所有标签页都同步显示同一个进度条,完全分不清哪个模型在运行、跑了多少进度。咱们来一步步解决这个问题,核心是让每个标签页的进度条和对应模型的生成逻辑精准绑定,互不干扰。
问题根源
你当前的代码里,虽然给每个标签页都加了gr.Progress组件,但有两个关键问题:
- 这些进度条组件没有被加入生成函数的输出列表,直接调用
progress_dict[model_name](...)只会触发全局临时进度条,导致所有标签页同步显示。 - 单个
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




