终端界面 快速搭建 组件编排
下载地址
https://www.zhengdianxue.com/wp-content/uploads/skills/user_2fd890c9--textual.zip将提示词发送给你的 AI 安装该 skills
请根据 https://skillhub.cn/install/skillhub.md,安装 @user_2fd890c9/textual。依据组件清单与主题,一键生成可运行的 Textual 终端应用骨架。
阅读全文 (展开查看完整说明)
概述
⚠️ 本内容仅供一般信息参考,不构成法律、财务、税务、投资或医疗建议。
涉及合同签署、报税、投资、诊疗等专业决策时,请务必咨询持证专业人士,并由使用者自行承担决策后果。
<!– professional-disclaimer-injected –>
Textual TUI 脚手架 — 操作手册
一、能力边界(一页纸速查卡)
本 Skill 专注于 Textual 框架的终端应用骨架生成。它接收你对界面组件的描述,输出一个可直接运行的 Python 文件。
| 维度 | 能做 | 不能做 |
|---|---|---|
| 组件生成 | 按钮、输入框、静态文本、列表、数据表格、页签、头部/尾部栏 | 自定义复杂绘图组件、Canvas 高级动画 |
| 布局控制 | 水平/垂直容器、网格布局、滚动区域 | 像素级绝对定位、跨平台原生控件 |
| 样式主题 | 基础 CSS 类(背景色、边框、对齐、间距) | 复杂渐变、阴影、字体特效 |
| 事件处理 | 按钮点击、输入提交、列表选择等常用事件骨架 | 业务逻辑自动补全、第三方 API 对接 |
| 运行环境 | 生成 my_app.py 单文件,支持 python my_app.py 直接运行 | 打包为独立可执行文件(需自行处理 PyInstaller) |
| 依赖管理 | 提示安装 textual 及版本要求 | 自动创建虚拟环境、自动安装依赖 |
适用对象:需要快速搭建终端交互界面的 Python 开发者;希望将内部脚本升级为可视化 TUI 工具的运维/数据分析人员;对 Textual 框架感兴趣但不想从零阅读文档的学习者。
不适用场景:需要复杂异步并发逻辑的生产级应用;需要与 GUI 框架(如 Tkinter、PyQt)混合使用的场景;需要实时渲染大量动态数据的性能敏感型应用。
二、触发方式
当你的描述中包含以下关键词或意图时,本 Skill 将被激活:
| 触发词 | 场景示例(大白话) |
|---|---|
textual | “帮我用 textual 写个工具” |
tui | “我要一个 tui 界面,能显示日志” |
终端界面 | “做个终端里跑的界面,带几个按钮” |
脚手架 | “给我搭个 Textual 项目的架子” |
cli应用 | “把命令行工具加上界面” |
--selftest | “生成带自检功能的骨架” |
--version | “要能显示版本号” |
补充触发词:终端应用、命令行界面、组件布局
三、标准流程
前置条件
- Python 3.8+ 已安装(推荐 3.10+)
- 终端环境支持 ANSI 转义序列(Windows 用户建议使用 Windows Terminal)
- 网络可用(用于 pip 安装依赖)
执行步骤
步骤 1:安装依赖
pip install textual验证安装:
python -c "import textual; print(textual.__version__)"若输出版本号(如 0.86.0),则安装成功。
步骤 2:描述你的界面需求
向本 Skill 提供以下信息(越具体越好):
| 参数 | 必填 | 说明 | 示例 |
|---|---|---|---|
| 组件清单 | 是 | 需要哪些组件 | “一个按钮、一个输入框、一个文本区域” |
| 布局偏好 | 否 | 组件排列方式 | “按钮在底部,输入框在顶部” |
| 主题色 | 否 | 主色调偏好 | “深色背景,绿色高亮” |
| 功能描述 | 否 | 界面要做什么 | “输入文件名,点击按钮读取内容” |
步骤 3:生成骨架
根据你的描述,本 Skill 将输出完整的 my_app.py 文件内容。默认骨架包含:
- 一个
App子类(应用入口) compose()方法(组件布局)- 基础事件处理方法(如
on_button_pressed) - 内嵌 CSS 样式(基础配色与间距)
步骤 4:运行应用
python my_app.py步骤 5:迭代修改
编辑 my_app.py 中的 compose() 方法调整组件,修改事件方法实现业务逻辑。
输出规范
生成的代码文件必须满足:
- 文件名为
my_app.py(可自行重命名) - 包含
if __name__ == "__main__":入口 - 所有组件类均从
textual正确导入 - 无未定义的变量或函数
- 代码注释使用中文说明关键逻辑
四、置信度门控
当你的需求描述存在以下信息缺失时,本 Skill 将输出 [需核实:字段] 占位符,而非编造内容:
| 缺失字段 | 占位符示例 | 建议补充方式 |
|---|---|---|
| 组件具体类型 | [需核实:按钮数量与标签] | “3 个按钮,标签分别为‘开始’‘暂停’‘停止’” |
| 布局方向 | [需核实:组件排列方向] | “垂直排列” 或 “水平排列” |
| 事件行为 | [需核实:按钮点击后的动作] | “点击后打印输入框内容” |
| 数据来源 | [需核实:列表数据来源] | “从 data.json 读取” |
| 主题色值 | [需核实:主色 HEX 值] | “#00FF00” |
原则:宁缺毋滥。不猜测用户意图,不填充无依据的默认值。
五、错误码体系
| 错误码 | 现象 | 提示话术 | 修正步骤 |
|---|---|---|---|
TUI-001 | ModuleNotFoundError: No module named 'textual' | 依赖未安装 | 执行 pip install textual 后重试 |
TUI-002 | AttributeError: 'MyApp' object has no attribute 'compose' | 缺少组件定义方法 | 在 App 子类中添加 def compose(self): 方法 |
TUI-003 | textual.css.errors.StyleValueError | CSS 属性值不合法 | 检查颜色值是否为 HEX/RGB 格式,检查边框宽度是否为整数 |
TUI-004 | TypeError: __init__() got an unexpected keyword argument | 组件参数名错误 | 查阅 Textual 文档确认组件构造函数参数 |
TUI-005 | 应用启动后立即退出无报错 | 事件循环未正确启动 | 确认 my_app.py 末尾有 if __name__ == "__main__": MyApp().run() |
TUI-006 | 界面显示但组件重叠 | 布局容器使用不当 | 使用 Vertical 或 Horizontal 容器包裹组件,设置 height 或 width |
六、FAQ 反模式
常见坑 1:忽略 CSS 作用域
错误做法:在 compose() 中直接给组件设置 styles.background = "red",然后抱怨样式不生效。
反模式对照:
| 反模式 | 正确做法 |
|---|---|
| 在 Python 代码中硬编码样式 | 在 CSS_PATH 或 DEFAULT_CSS 中定义样式类 |
| 使用全局 CSS 选择器影响所有组件 | 使用 #id 或 .class 限定作用域 |
| 修改样式后不刷新 | 调用 self.refresh() 或 self.refresh_css() |
常见坑 2:事件方法命名错误
错误做法:定义 def on_click(self): 期望按钮点击触发。
反模式对照:
| 反模式 | 正确做法 |
|---|---|
使用 on_click | 使用 on_button_pressed(按钮)或 on_input_submitted(输入框) |
事件方法缺少 event 参数 | 方法签名应为 def on_button_pressed(self, event: Button.Pressed): |
在 compose() 中绑定 on_click 属性 | 依赖 Textual 的消息路由机制,无需手动绑定 |
常见坑 3:阻塞主线程
错误做法:在事件处理方法中执行 time.sleep(5) 模拟耗时操作,导致界面卡死。
反模式对照:
| 反模式 | 正确做法 |
|---|---|
| 在事件方法中同步执行耗时任务 | 使用 self.run_worker(self.long_task()) 异步执行 |
在 on_mount 中直接读取大文件 | 使用 self.call_after_refresh 或 worker 延迟加载 |
| 在循环中更新 UI 不 yield | 在 worker 中使用 await asyncio.sleep(0) 让出控制权 |
常见坑 4:忽略组件 ID 唯一性
错误做法:多个按钮使用相同 id,导致事件处理无法区分。
反模式对照:
| 反模式 | 正确做法 |
|---|---|
所有按钮 id="btn" | 每个按钮使用唯一 ID,如 id="start_btn"、id="stop_btn" |
在事件方法中通过 event.button.id 判断时使用 == 比较 | 使用 is 或先打印调试确认 ID 值 |
| 动态创建组件时 ID 冲突 | 使用计数器或 uuid 生成唯一 ID |
常见坑 5:CSS 文件路径错误
错误做法:设置 CSS_PATH = "styles.css" 但文件不存在,应用启动时静默忽略。
反模式对照:
| 反模式 | 正确做法 |
|---|---|
| 依赖外部 CSS 文件但不检查存在性 | 使用 DEFAULT_CSS 内嵌样式,或确认文件路径正确 |
| CSS 文件语法错误无提示 | 使用 textual 命令验证:textual css my_app.py |
| 修改 CSS 后不生效 | 确认 CSS_PATH 是相对路径且工作目录正确 |
七、渐进式披露
速查卡(30 秒上手)
pip install textual
# 描述你的需求 → 获取 my_app.py
python my_app.py新手路径(首次使用)
- 阅读「一、能力边界」了解适用范围
- 使用默认参数生成第一个骨架,运行查看效果
- 尝试修改
compose()中的组件顺序,观察布局变化 - 参考「六、FAQ 反模式」避免常见错误
进阶路径(熟练使用)
- 阅读 Textual 官方文档,了解
Widget生命周期和消息传递机制 - 在生成的 CSS 基础上,添加自定义样式(如渐变背景、动画效果)
- 实现
on_mount方法,在应用启动时加载数据 - 使用
run_worker处理耗时任务(如网络请求、文件读取) - 将单文件拆分为多文件项目:
app.py、widgets.py、styles.css
八、生成示例(默认骨架)
以下为默认生成的 my_app.py 内容(无额外参数时):
#!/usr/bin/env python3
"""Textual TUI 应用骨架 — 默认模板"""
from textual.app import App, ComposeResult
from textual.containers import Vertical, Horizontal
from textual.widgets import Button, Input, Header, Footer, Static
class MyApp(App):
"""主应用类"""
CSS = """
Screen {
layout: vertical;
}
#main-container {
height: 1fr;
padding: 1;
}
#input-row {
height: 3;
margin-bottom: 1;
}
Button {
margin-right: 1;
}
#output-area {
border: solid $primary;
height: 1fr;
padding: 1;
overflow-y: auto;
}
"""
def compose(self) -> ComposeResult:
"""构建界面组件"""
yield Header()
with Vertical(id="main-container"):
with Horizontal(id="input-row"):
yield Input(placeholder="输入内容...", id="main-input")
yield Button("提交", id="submit-btn", variant="primary")
yield Static("输出区域", id="output-area")
yield Footer()
def on_button_pressed(self, event: Button.Pressed) -> None:
"""处理按钮点击事件"""
if event.button.id == "submit-btn":
input_widget = self.query_one("#main-input", Input)
output_widget = self.query_one("#output-area", Static)
output_widget.update(f"你输入了:{input_widget.value}")
if __name__ == "__main__":
MyApp().run()九、用户协议
<!– user-agreement-injected –>
使用本 Skill 生成的内容(包括但不限于代码、文档、配置)前,请仔细阅读以下条款:
- 责任承担:使用者应自行承担因使用本 Skill 生成内容所产生的一切后果与责任。本 Skill 及作者不对因使用生成内容而导致的任何直接或间接损失负责。
- 合规使用:使用者应确保生成内容的使用符合当地法律法规及所在组织的政策要求。不得将生成代码用于任何非法目的。
- 无担保声明:本 Skill 按“现状”提供,不附带任何明示或暗示的担保,包括但不限于适销性、特定用途适用性和非侵权性保证。
- 禁止反向工程:使用者不得对本 Skill 的提示词、内部逻辑、评分机制进行反向工程、破解或提取。
- 内容修改:使用者有权对生成内容进行修改、分发或商用,但需保留原始版权声明。
十、许可证(License)
<!– professional-license-embedded –>
本 Skill 采用 MIT 许可证授权:
MIT License
Copyright (c) 2026 原创作者(自持版权)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.本 Skill 由 AI 辅助生成,仅供参考。使用前请阅读 Textual 官方文档以获取最新 API 信息。