当前位置:首页>python>怎么用 Python 写终端界面?Textual 让命令行长出按钮和输入框

怎么用 Python 写终端界面?Textual 让命令行长出按钮和输入框

  • 2026-10-01 23:28:16
怎么用 Python 写终端界面?Textual 让命令行长出按钮和输入框

"

命令行也能长出按钮和输入框,Textual 让写软件不再需要前端。

提到「做个带界面的小程序」,大多数人第一反应是:装个 PyQt、写点 HTML,或者干脆放弃。但有一个 Python 库,让你只用终端,就能写出带按钮、表格、输入框、甚至鼠标交互的全屏应用——它就是 Textual。

📌 本文看点

01

什么是 Textual

02

四大核心能力

03

动手写待办应用

01

WHAT IS IT

它是什么

Textual 是 Rich(就是你之前认识的那个命令行美化库)作者 Will McGugan打造的一个 TUI 框架(终端用户界面)。

它的核心思路很妙:用 Python 写逻辑,用 CSS 写样式。你写的代码跑在终端里,但呈现出来的却是一个有布局、有组件、能点能输的「软件界面」。

为什么要选它,而不是传统方案?

PyQt / Tkinter

不用装庞大的 GUI 运行环境,打包分发都更轻。

Web 框架

不需要浏览器、不需要前端三件套,一个终端窗口就够。

跨平台

Linux / macOS / Windows 的终端(甚至 Windows Terminal)都能跑,而且原生支持鼠标和键盘。

换句话说,当你只想给团队做一个内部小工具、给运维做一个监控面板、或者给自己写个本地效率工具时,Textual 是那条成本最低、交付最快的路。

02

CORE FEATURES

核心功能

1. 类 CSS 的样式系统

Textual 用一套和网页 CSS 很像的语法来排版终端组件:可以设置颜色、边距、对齐,还支持 grid和 flex布局。最爽的是——它支持热重载,改完样式保存,界面立刻更新,不用重启。

2. 开箱即用的组件库

按钮 Button、输入框 Input、数据表格 DataTable、树 Tree、标签页 TabbedContent、进度条、甚至是 Markdown 渲染组件,全都内置。你几乎不用从零画组件。

3. 事件驱动

像前端一样响应用户操作:on_button_pressed(按钮被点)、on_input_submitted(输入框回车)、on_mount(界面加载完成)……逻辑清晰,好维护。

4. 异步友好

底层基于 asyncio,耗时的网络请求、文件读写放在后台,界面也不会卡住。

03

GET STARTED

使用方法

安装只要一行:

...bash

pip install textual

装完可以先体验官方自带的组件大赏,直接在终端里跑起来看效果:

...bash

python -m textual

这会打开一个展示各种组件和样式的演示界面,非常适合「先看再学」。

最小可运行例子长这样——一个会响应点击的窗口:

...python

from textual.app import App, ComposeResult

from textual.widgets import Header, Footer, Static, Button

class HelloApp(App):

  def compose(self) -> ComposeResult:

    yield Header()

    yield Static("Hello, Textual!",id="msg")

    yield Button("点我",id="btn")

    yield Footer()

  def on_button_pressed(self, event: Button.Pressed) -> None:

    self.query_one("#msg", Static).update("你点到我了!")

HelloApp().run()

保存为 app.py,执行 python app.py,一个带标题栏、正文和按钮的终端窗口就出现了。

04

CASE STUDY

案例代码:终端待办清单

下面这个例子稍微完整一点——一个能在终端里增删待办的小应用,覆盖输入、按钮、列表三种组件。复制即可运行:

...python

from textual.app import App, ComposeResult

from textual.containers import Vertical

from textual.widgets import Header, Footer, Input, Button, ListView, ListItem, Label

class TodoApp(App):

  CSS = """

#row { height: 3; }

Input { width: 1fr; }

Button { width: 12; }

  """

  def compose(self) -> ComposeResult:

    yield Header()

    yield Vertical(

      Input(placeholder="输入待办,回车添加",id="todo-input"),

      Button("添加",id="add-btn"),

      ListView(id="todo-list"),

    )

    yield Footer()

  def on_button_pressed(self, event: Button.Pressed) -> None:

    self._add()

  def on_input_submitted(self, event: Input.Submitted) -> None:

    self._add()

  def _add(self) -> None:

    inp = self.query_one("#todo-input", Input)

    text = inp.value.strip()

    if not text:

      return

    self.query_one("#todo-list", ListView).append(

      ListItem(Label(text))

    )

    inp.value = ""

if __name__ == "__main__":

  TodoApp().run()

「运行后,在输入框打字、回车或点「添加」,待办就会实时出现。短短三十多行,一个能用的小工具就成型了——这正是 Textual 的魅力:把「写界面」的门槛,降到和普通脚本一样低。」

∞

THE END

写在最后

Textual 适合那些「不想碰前端、却又想要个界面」的场景:内部运维面板、本地数据查看器、CLI 工具的增强版外壳。它不取代 Web 或桌面 GUI,但在「轻量交付」这个区间里,几乎没有对手。

「如果你已经用熟了 Rich,那 Textual 几乎是顺理成章的下一步——毕竟,会画彩色文字,下一步自然是想画整个界面。」

END

如果你觉得今天这篇有收获,欢迎点赞、在看、转发三连,我们下篇见。

最新文章

随机文章