在终端应用程序的世界里,过去的交互方式通常是简单的命令行输入和文本输出。然而,随着开发者对更高可用性和更友好界面的追求,现代终端用户界面(TUI,Terminal User Interface)工具逐渐受到关注。Textual 便是其中的佼佼者。
Textual 是一个基于 Python 的 TUI 框架,它能够帮助开发者轻松构建美观且交互性强的终端应用程序。它借鉴了 Web 开发中的前端设计理念,如响应式布局、组件化开发等,使得终端界面可以像 GUI 应用一样流畅。
本文将深入介绍 Textual 库的核心概念、主要功能以及实际应用场景,并通过示例代码展示如何利用 Textual 开发一个现代化的终端应用。
Textual 是由 Will McGugan(Rich 库的作者)开发的一个用于构建终端 UI 应用的框架。它基于 rich
库,提供了一整套现代化的终端 UI 组件,支持以下特性:
rich
进行文本样式化,如颜色、加粗、斜体等。div
布局方式,可创建复杂界面。要使用 Textual,首先需要安装它。可以通过 pip
直接安装:
pip install textual
安装完成后,你可以运行 textual demo
命令来查看官方的演示示例。
Textual 提供了一种类似前端开发的方式来构建 TUI 应用,核心概念包括 应用(App)、小部件(Widget)、事件(Event)、CSS 样式 等。
Textual 的 App
类是所有应用的入口点。所有的 TUI 应用都需要继承 textual.app.App
进行开发。
from textual.app import App
class MyApp(App):
def on_mount(self) -> None:
self.log("应用已启动")
MyApp().run()
运行后会显示一个空白的终端界面,并在日志中打印 "应用已启动"
。
Textual 采用组件化的方式组织 UI,所有可视化组件都是 Widget
。
from textual.app import App
from textual.widgets import Label
class MyApp(App):
def on_mount(self):
self.mount(Label("Hello, Textual!"))
MyApp().run()
在屏幕上会显示 Hello, Textual!
,Label
就是一个 Widget
。
Textual 使用事件驱动机制,例如键盘输入、鼠标点击等。
from textual.app import App
from textual.events import Key
class MyApp(App):
def on_key(self, event: Key) -> None:
self.log(f"按键:{event.key}")
MyApp().run()
每当用户按下键盘,都会在日志中显示按下的按键。
Textual 允许使用类似 CSS 的语法进行界面样式化。
from textual.app import App
from textual.widgets import Label
class MyApp(App):
CSS = """
Label {
color: green;
text-align: center;
}
"""
def on_mount(self):
self.mount(Label("绿色文本"))
MyApp().run()
下面,我们使用 Textual 构建一个简单的 任务管理应用,包含任务列表、输入框、添加按钮等。
from textual.app import App, ComposeResult
from textual.widgets import Header, Footer, Button, Input, ListView, ListItem, Static
from textual.containers import Vertical, Horizontal
class TaskApp(App):
CSS = """
Screen {
layout: vertical;
}
Input {
width: 80%;
}
"""
def compose(self) -> ComposeResult:
yield Header()
yield Vertical(
Horizontal(Input(placeholder="输入任务..."), Button("添加", id="add")),
ListView(id="task_list"),
Footer(),
)
def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "add":
task_input = self.query_one(Input)
task_list = self.query_one(ListView)
if task_input.value.strip():
task_list.mount(ListItem(Static(task_input.value.strip())))
task_input.value = ""
TaskApp().run()
ListView
组件。运行代码后,用户可以在输入框输入任务,按下 “添加” 按钮,任务会显示在列表中。
除了基础的 UI 组件和事件处理,Textual 还支持以下高级功能:
from textual.app import App
from textual.widgets import Markdown
class MarkdownApp(App):
def on_mount(self):
self.mount(Markdown("# 这是一个 Markdown 组件\n- 支持列表\n- 代码高亮"))
MarkdownApp().run()
from textual.app import App
from textual.widgets import Label
from textual.reactive import Reactive
class AnimatedApp(App):
counter = Reactive(0)
def compose(self):
yield Label("0", id="counter")
async def on_mount(self):
while True:
self.query_one("#counter").update(str(self.counter))
self.counter += 1
await self.sleep(1)
AnimatedApp().run()
该应用会每秒更新一次 Label
显示的数字,实现简单的动画效果。
Textual 适用于各种终端应用,包括:
Textual 让终端 UI 变得更加现代化和交互性强,为开发者提供了一种高效的方式来构建 TUI 应用。通过 Widget
组件化开发、CSS 样式控制、事件驱动机制,我们可以快速搭建复杂的终端应用。
如果你对终端 UI 开发感兴趣,Textual 绝对值得一试!