当前位置: 首页 > news >正文

Python文本用户界面curses

【curses 文本用户界面 —— 终端中的图形界面编程】
# 本示例演示 Python curses 库的核心功能:屏幕控制、键盘输入、窗口和面板、颜色、菜单导航

import curses
import curses.textpad

# ---------- 主函数 ----------
def main(stdscr):
"""curses 程序入口——所有 curses 操作需要在包装函数中完成"""

# ---------- 1. 初始化设置 ----------
# 关闭键盘回显(输入字符不在屏幕上显示)
curses.noecho()

# 关闭行缓冲(立即读取按键,无需按回车)
curses.cbreak()

# 启用特殊键码解析(方向键、功能键等)
stdscr.keypad(True)

# 设置光标不可见(0=可见, 1=非常可见, 2=完全不可见)
curses.curs_set(0)

# ---------- 2. 颜色支持 ----------
# 检查终端是否支持颜色
if curses.has_colors():
curses.start_color()
# 初始化颜色对:数字索引, 前景色, 背景色
curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK) # 标题
curses.init_pair(2, curses.COLOR_GREEN, curses.COLOR_BLACK) # 选中项
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK) # 提示
curses.init_pair(4, curses.COLOR_RED, curses.COLOR_BLACK) # 警告
curses.init_pair(5, curses.COLOR_WHITE, curses.COLOR_BLUE) # 高亮
curses.init_pair(6, curses.COLOR_BLACK, curses.COLOR_WHITE) # 反色

# 获取颜色对(方便调用)
COLOR_TITLE = curses.color_pair(1) | curses.A_BOLD
COLOR_SELECTED = curses.color_pair(2) | curses.A_BOLD
COLOR_HINT = curses.color_pair(3)
COLOR_WARN = curses.color_pair(4) | curses.A_BOLD
COLOR_HIGHLIGHT = curses.color_pair(5)
COLOR_INVERSE = curses.color_pair(6)

# ---------- 3. 获取终端尺寸 ----------
max_y, max_x = stdscr.getmaxyx()

# ---------- 4. 创建子窗口(窗口和面板演示)----------
# 标题窗口
title_win = curses.newwin(3, max_x, 0, 0)

# 菜单窗口(左侧导航)
menu_win = curses.newwin(max_y - 6, 20, 3, 0)

# 内容窗口(右侧主区域)
content_win = curses.newwin(max_y - 6, max_x - 21, 3, 20)

# 状态栏窗口(底部)
status_win = curses.newwin(3, max_x, max_y - 3, 0)

# ---------- 5. 定义菜单数据 ----------
menu_items = [
("首页", "欢迎使用 curses 文本界面\n\ncurses 是 Unix/Linux 下\n开发 TUI 的标准库。"),
("文件管理", "文件管理功能演示区域\n\n- 新建文件\n- 打开文件\n- 保存文件"),
("系统设置", "系统设置项\n\n1. 显示设置\n2. 声音设置\n3. 网络设置"),
("帮助", "操作指南\n\n↑/↓ 移动菜单\nEnter 选中\nq 退出程序"),
]
current_idx = 0 # 当前选中的菜单索引

# ---------- 6. 绘制函数 ----------
def draw_title():
"""绘制标题栏"""
title_win.clear()
title_win.bkgd(curses.color_pair(5))
title_text = " curses 文本用户界面演示 "
x_center = max_x // 2 - len(title_text) // 2
title_win.addstr(1, x_center, title_text, COLOR_INVERSE)
title_win.noutrefresh()

def draw_menu():
"""绘制菜单列表"""
menu_win.clear()
menu_win.box()

for idx, (item_name, _) in enumerate(menu_items):
if idx == current_idx:
# 当前选中项使用高亮颜色
menu_win.addstr(2 + idx * 2, 2, f"> {item_name}",
COLOR_SELECTED)
else:
menu_win.addstr(2 + idx * 2, 2, f" {item_name}",
COLOR_TITLE)

menu_win.noutrefresh()

def draw_content():
"""绘制内容区域"""
content_win.clear()
content_win.box()

# 获取当前选中菜单的内容
_, content = menu_items[current_idx]
lines = content.split("\n")
for i, line in enumerate(lines):
if i == 0:
# 第一行作为内容标题
content_win.addstr(1, 2, line,
COLOR_TITLE if current_idx != current_idx
else COLOR_SELECTED)
else:
content_win.addstr(3 + i - 1, 4, line)

content_win.noutrefresh()

def draw_status():
"""绘制状态栏"""
status_win.clear()
status_win.bkgd(curses.color_pair(5))
status_text = (f" 选中: {menu_items[current_idx][0]} "
f"| 终端: {max_y}x{max_x} "
f"| 使用方向键导航 | q 退出")
status_win.addstr(1, 2, status_text, COLOR_INVERSE)
status_win.noutrefresh()

# ---------- 7. 初始绘制 ----------
draw_title()
draw_menu()
draw_content()
draw_status()
# doupdate() 一次性刷新所有窗口(比单独 refresh 更高效)
curses.doupdate()

# ---------- 8. 主事件循环 ----------
while True:
# 获取按键输入(阻塞等待)
key = stdscr.getch()

# ---- 菜单导航 ----
if key == curses.KEY_UP:
current_idx = (current_idx - 1) % len(menu_items)
elif key == curses.KEY_DOWN:
current_idx = (current_idx + 1) % len(menu_items)
elif key == curses.KEY_ENTER or key in (10, 13):
# 回车键选中当前项目(显示确认消息)
content_win.addstr(8, 4, f">>> 已选中: {menu_items[current_idx][0]} <<<",
COLOR_WARN)
content_win.noutrefresh()
curses.doupdate()
curses.napms(500) # 暂停 500ms
elif key == ord("q") or key == ord("Q"):
# 退出程序
break
elif key == curses.KEY_RESIZE:
# 终端尺寸变化时重新获取
max_y, max_x = stdscr.getmaxyx()
# 重新调整窗口大小
title_win.resize(3, max_x)
menu_win.resize(max_y - 6, 20)
content_win.resize(max_y - 6, max_x - 21)
status_win.resize(3, max_x)
# 移动窗口位置
content_win.mvwin(3, 20)
status_win.mvwin(max_y - 3, 0)

# ---- 重绘所有窗口 ----
draw_title()
draw_menu()
draw_content()
draw_status()
curses.doupdate()

# ---------- 9. 恢复终端设置 ----------
curses.nocbreak()
stdscr.keypad(False)
curses.echo()
curses.curs_set(1)
curses.endwin()

# ---------- 包装器入口 ----------
if __name__ == "__main__":
# curses.wrapper() 负责初始化、异常处理和终端恢复
curses.wrapper(main)

http://www.rkmt.cn/news/1428762.html

相关文章:

  • ESP8266-01s烧录MQTT固件避坑指南:从选固件到接线,一次搞定阿里云连接
  • 护网行动内幕:为什么有人能连续5年打国家级项目?他们的训练方法终于公开了!
  • 杉德斯玛特服务卡闲置了,三种方法,新手也能一键回收 - 淘淘收小程序
  • 石家庄美团代运营哪家好?2026头部运营机构实力见证 - GrowthUME
  • ESP8266驱动OLED动画:从像素编辑到代码自动生成的机器人眼睛方案
  • 郑州市巩义市适老化改造|维小达 专业适老厨房、适老卫生间、全屋适老化、个性化适老定制一站式服务 - 维小达科技
  • 基于Arduino与1602 LCD的避障游戏开发:从硬件搭建到软件架构全解析
  • 从OpenCV到自动驾驶:聊聊RANSAC算法在图像匹配与车道线检测里的实战调参
  • Keil C编译器运行时库中断问题分析与优化
  • 使用srec_cat工具实现二进制数据到C数组的高效转换
  • 2026年上海超声波焊接机厂家实力评测:江浙沪采购商如何找到真正靠谱的焊接设备源头? - 优质企业观察收录
  • 利用红外LED与摄像头特性制作万圣节幽灵发光眼装置
  • Ubuntu 20.04 上 Geant4 安装避坑全记录:从源码编译到 B1 示例跑通(含数据包加速下载)
  • WrenAI终极指南:5分钟为AI智能体构建企业数据上下文层
  • 2026年唐山搬家公司实测排行 靠谱服务核心维度解析 - 奔跑123
  • 2026年唐山设备搬运公司排行:从资质到服务的客观盘点 - 奔跑123
  • Playwright连接浏览器踩坑实录:解决端口占用、路径错误和连接超时
  • 2026人物抠图保姆级指南:免费好用的工具这样选(附详细教程) - AI测评专家
  • 2026年上海超声波焊接机厂家深度评测:江浙沪采购必读,附刘工直达联系方式 - 优质企业观察收录
  • 3分钟解锁你的加密音乐库:浏览器一键解密全攻略
  • 近一年AI漫剧制作厂商多家实力测评 - 速递信息
  • 自适应量化与多传感器融合的陨石坑检测系统
  • Arm架构GIC版本识别方法与实战解析
  • 为什么92%的Gemini集群在QPS破万后出现隐性OOM?深度拆解内存隔离、CUDA上下文缓存与cgroup v2的致命协同失效
  • 3步完成:OpenCore Configurator图形化配置黑苹果引导
  • 实地探访箭金学堂 ——浙江成人学历提升的靠谱之选 - 浙江教育测评
  • AI(大模型/代码助手)写代码的准确率、质量 开发语言排行榜
  • 合肥黄金回收避坑全攻略!2026年5月上门回收防骗指南,述姗博伦领勤三家实测 - 余生黄金回收
  • 传承文化,诚信回收,京城信德斋守护每一件珍贵字画 - 深鉴新闻
  • 5分钟上手VisualGGPK2:解锁《流放之路》游戏资源编辑的终极神器