入门 Eva J Patel(freeCodeCamp) 2026-09-10 16:14:02 · 0 阅读

第9章 Gradio 布局:行、列、标签页与 Blocks

界面能运行,不代表就是好界面。

想象一下,打开一个应用,看到二十个组件竖着堆成一列。

一切功能正常,技术上也没任何问题,但想找到需要的东西却让人身心俱疲。

好的界面设计会把相关的控件组织在一起,并把应用的不同部分区分开来。

Gradio 的布局系统正是为此而生。

为什么布局很重要

以一个文档分析器为例。

它可能包含:

  • 文件上传器,

  • 文本预览,

  • 分析设置,

  • 按钮,

  • 摘要,

  • 表格,

  • 以及聊天区域。

把所有组件塞进一根长长的竖列并不理想。更好的做法是把应用划分成几个区块来组织。

Gradio 的 Blocks API 正是构建这类界面的基础。

Blocks 开始

一个基础应用长这样:

import gradio as gr

with gr.Blocks() as demo:
    gr.Markdown("# My Application")

demo.launch()

Blocks 上下文内的所有内容都属于这个应用。

行(Rows)

Row 会让组件水平排列。

例如:

with gr.Blocks() as demo:
    with gr.Row():
        first = gr.Textbox(label="First")
        second = gr.Textbox(label="Second")

demo.launch()

在布局空间允许的情况下,两个文本框会并排显示。

Row 特别适合放置相互关联的控件。

示例:两数计算器

import gradio as gr

def add(a, b):
    return a + b

with gr.Blocks() as demo:
    gr.Markdown("# Calculator")

    with gr.Row():
        a = gr.Number(label="First Number")
        b = gr.Number(label="Second Number")

    button = gr.Button("Add")

    result = gr.Number(label="Result")

    button.click(
        fn=add,
        inputs=[a, b],
        outputs=result
    )

demo.launch()

两个输入框在逻辑上相关,放在一行里就很合理。

列(Columns)

Column 会让组件垂直堆叠。

with gr.Column():
    name = gr.Textbox()
    age = gr.Number()
    button = gr.Button()

Blocks 应用默认就是纵向排列的,但在嵌套布局时,显式使用 Column 会特别有用。

组合 Row 和 Column

布局设计在此时真正体现出威力。一个 Row 里可以包含两个 Column。

例如:

with gr.Row():
    with gr.Column():
        input_text = gr.Textbox()
        button = gr.Button("Analyze")

    with gr.Column():
        output = gr.Textbox()

这就形成了一个常见的应用模式:

  • 一侧放控件

  • 另一侧显示结果

构建双面板界面

我们来创建一个简单的文本分析器。

import gradio as gr

def analyze(text):
    return (
        f"Characters: {len(text)}\n"
        f"Words: {len(text.split())}"
    )

with gr.Blocks() as demo:
    gr.Markdown("# Text Analyzer")

    with gr.Row():
        with gr.Column():
            text = gr.Textbox(
                label="Input Text",
                lines=12
            )

            button = gr.Button("Analyze")

        with gr.Column():
            result = gr.Textbox(
                label="Analysis",
                lines=12
            )

    button.click(
        fn=analyze,
        inputs=text,
        outputs=result
    )

demo.launch()

到这里,已经不像示例拼凑,而像一个真正的应用了。

缩放与布局比例

可以通过配置控制 Row 和 Column 的相对大小。

例如:

with gr.Row():
    with gr.Column(scale=2):
        input_text = gr.Textbox()

    with gr.Column(scale=1):
        output = gr.Textbox()

第一列获得的空间比第二列更大。当应用某侧需要明显更多空间时,这种配置非常实用。

比如,大段文档输入区往往需要比小型设置面板更多的空间。

Tabs

当应用包含多个相关联的工作流时,Tabs 就派得上用场了。

例如:

with gr.Blocks() as demo:
    with gr.Tab("Text Analyzer"):
        ...

    with gr.Tab("Image Analyzer"):
        ...

demo.launch()

用户可以在两个工具之间切换,而不必同时看到所有控件。

什么时候该用 Tabs?

Tabs 适用于以下场景:

  • 工作流之间有关联

  • 用户不需要同时使用两个工作流

  • 每个工作流包含多个控件

  • 否则界面会变得杂乱

不要为了用 Tabs 而用。如果一个应用只有两小块内容,Tabs 反而会增加不必要的操作成本。

示例:多工具应用

想象一个 AI 效率工具,包含:

  • 摘要生成器

  • 翻译器

  • 文本分析器

你可以这样搭建:

with gr.Blocks() as demo:

    gr.Markdown("# AI Productivity Tools")

    with gr.Tab("Summarizer"):
        ...

    with gr.Tab("Translator"):
        ...

    with gr.Tab("Text Analyzer"):
        ...

demo.launch()

每个 Tab 就是一个独立的工作流。

分组

分组可以将相关组件组织在一起,而不必单独开一个 Tab。比如把几项设置放在一起。

具体的视觉表现取决于当前 Gradio 版本和主题,但核心思路很简单:把相关的控件放在一起。

折叠面板

当有可选或高级设置时,折叠面板(Accordion)很有用。

想象一个 AI 应用,包含:

  • 提示词

  • 模型

  • 温度参数

  • 最大 token 数

  • 高级采样设置

  • 系统指令

大多数用户可能只关心提示词。

你可以把高级控件放进一个折叠面板里。

概念上:

with gr.Accordion("Advanced Settings"):
    temperature = gr.Slider(...)
    max_tokens = gr.Slider(...)

这样既保持了主界面的简洁,又给高级用户留出了操作空间。

可见性

有时候,你希望组件只在需要时才显示。

比如,一个应用最初可能显示:

Choose input type

用户选了"Image",就显示图片上传组件;选了"Text",则改为显示文本框。

Gradio 支持通过事件动态修改组件属性,这是构建更简洁界面的一个强大技巧。

条件式界面

假设我们有:

input_type = gr.Radio(
    choices=["Text", "Image"],
    label="Input Type"
)

我们可以在用户改变选择时,显示对应的组件。

具体的更新语法要与你使用的 Gradio 版本相匹配,但设计模式是这样的:

User chooses mode
        ↓
Event fires
        ↓
Interface updates
        ↓
Relevant component becomes available

对于支持多种输入模式的应用来说,这非常实用。

用 Markdown 做设计元素

别小看 Markdown。你可以用它来构建层次结构:

gr.Markdown("# AI Assistant")
gr.Markdown("## Upload a document")
gr.Markdown("Choose a file to begin.")

一段写得好的说明文字,能让技术界面好用很多。

区分输入与输出区域

一个常用的设计模式是:

gr.Markdown("## Input")
...
gr.Markdown("## Results")
...

例如:

with gr.Blocks() as demo:
    gr.Markdown("# Document Analyzer")

    gr.Markdown("## Upload a document")

    file = gr.File()

    gr.Markdown("## Analysis")

    result = gr.Textbox(lines=10)

这样就构建出了视觉上的层次结构,完全不需要写自定义前端代码。

一个完整的布局示例

接下来,我们把前面讲过的几种布局概念组合起来。

import gradio as gr

def analyze(text):
    words = len(text.split())
    characters = len(text)

    return words, characters

with gr.Blocks() as demo:
    gr.Markdown(
        "# Text Analyzer\n"
        "Analyze the text you provide."
    )

    with gr.Row():
        with gr.Column(scale=2):
            gr.Markdown("### Input")

            text = gr.Textbox(
                label="Text",
                lines=12
            )

            analyze_button = gr.Button(
                "Analyze",
                variant="primary"
            )

        with gr.Column(scale=1):
            gr.Markdown("### Results")

            words = gr.Number(
                label="Words"
            )

            characters = gr.Number(
                label="Characters"
            )

    analyze_button.click(
        fn=analyze,
        inputs=text,
        outputs=[words, characters]
    )

demo.launch()

这是一个布局与功能协同工作的典型示例。

响应式设计

用户可能在不同尺寸的屏幕上使用你的应用。在大显示器上看起来完美的布局,到了小屏上可能就会显得拥挤不堪。

不要假设每个用户都有大显示器。

行和列的使用要讲究分寸。如果两个组件本身就很宽,并排放置在小屏上会很难操作。

不要过度设计界面

人们总想把所有布局功能都用上。

你可能会做出这样的界面:

  • 五个 Tabs

  • 三个手风琴面板

  • 嵌套的行

  • 嵌套的列

  • 多个分组

  • 几十条 Markdown 标题

这样会让界面变得更难理解。

从最简单的布局开始,只要能把操作流程表达清楚就够了。

围绕用户的任务来设计

一个有用的思考起点是:

用户首先要做什么?

把那个操作放在最显眼的位置。

然后问:

他们需要提供哪些信息?

把这些输入框放在一起。

接着:

操作完成后他们应该看到什么?

把结果放在一个显而易见的位置。这样就形成了自然的流程。

示例:文档分析器布局

一个合理的文档分析器可以这样组织:

with gr.Blocks() as demo:
    gr.Markdown("# Document Analyzer")

    with gr.Row():
        with gr.Column():
            file = gr.File(label="Upload Document")
            analyze_button = gr.Button("Analyze")

        with gr.Column():
            summary = gr.Textbox(
                label="Summary",
                lines=10
            )

用户一看就懂:上传文件、点击分析、查看结果。

Tabs 还是独立应用

如果两个工具彼此无关,用 Tabs 未必是最佳选择。

比如,把房贷计算器和图像分类器塞进同一个应用,体验不一定更好。

Tabs 最适合用于同一产品内的不同工作流。

布局本身就是功能

这里有个关键认知:布局不只是装饰。

假设某个 AI 应用把"生成"按钮藏在二十个不相关的控件下面。

功能上没问题,但界面让人用起来更费劲。好的布局能降低认知负荷。

动手试试

挑一个你之前写过的应用,重新设计布局。

用到以下元素:

  • 一个标题

  • 一段简短描述

  • 至少一行 Row

  • 至少两列 Column

  • 一个输入区域

  • 一个输出区域

  • 一个高级设置 Accordion

不要为了凑清单而加布局元素,想想每个元素为什么应该放在那里。

要点总结

  • Blocks 让你掌控 Gradio 应用的结构。

  • Rows 让组件水平排列。

  • Columns 让组件垂直排列,并能控制相对空间占比。

  • Tabs 用于划分相关工作流。

  • Accordions 适合放可选或高级设置。

  • Markdown 可以建立视觉和信息层次。

  • 好的布局让应用更易理解、更易使用。

  • 响应式设计很重要,因为用户的屏幕尺寸各不相同。

  • 能清晰支持用户任务的最简单界面,往往就是最好的界面。

  • 评论 (0)