curses是一个提供终端屏幕打印和键盘处理的库, 我个人的理解就是终端里的gui(当然它是基于文本的)... 写2048的时候用到了这个库, 所以现在过来好好研究一下这个库...

下面是文档内容 :

首先在你做任何事之前, 你必须先调用 initscr() 初始化curses, 这个函数主要的作用是决定当前终端的类型, 然后发送一些必要的设置给终端, 并且创建独立的内部数据结构. 如果成功初始化的话, 该函数会返回一个代表屏幕的对象, 我们通常称为 stdscr (C语言就有的惯例). 另一方面, 正常情况下, 我们在终端上打字时, 你输入一个a终端上就会出现一个a, 但是对于curses编程来说这往往是没有必要的, 我们可以用 noecho() 来关掉它. 同时我们也需要按键之后得到立即响应而不是傻傻地回车之后再响应, 所以我们需要把输入模式改成 cbreak 模式而不是通常的缓冲输入模式, 这需要调用 cbreak() . 同时, 我们输入过程中有很多特别的键位, 比如方向键上下左右等等, 我们需要特殊处理这些键位的话, 我们可以调用 keypad(True), 这样的话, 按下左键位将返回一个类似 KEY_LEFT 的特殊值.  如果你需要结束终端的话, 只需要把你上面对终端进行的定制化设置关闭即可 :

import curses

#开启
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(True) #关闭, 回复正常终端
curses.nocbreak()
stdscr.keypad(False)
curses.echo()
curses.endwin()

但是这样其实是有问题的, 当遇到程序半途出现异常然后游戏直接非正常关闭的情况时, 这样会使得终端变得很奇怪... 所以python中加入了另外一个函数来帮助我们解决这个问题, 也就是 wrapper(), 该函数需要一个可调用作为参数, 并完成上述的初始化过程,  同时初始化颜色如果当前终端提供了对颜色的支持的话, 一旦调用对象返回, 该函数会自动重载调用前的终端状态, 因为该函数的内部使用try-catch 实现的, 它在出现异常时也会先回复终端, 然后再次生成异常, 所以在解决了终端问题的同时仍然正常打印异常信息...

 from curses import wrapper

 def main(stdscr):
# Clear screen
stdscr.clear() # This raises ZeroDivisionError when i == 10.
for i in range(0, 11):
v = i-10
stdscr.addstr(i, 0, '10 divided by {} is {}'.format(v, 10/v)) stdscr.refresh()
stdscr.getkey() wrapper(main)

在curses中, 窗口对象是最基本的抽象, 它代表长方形的屏幕区域, 支持显示文本, 文本擦除 以及用户输入. 之前提到的 stdscr 就是一个窗口对象, 它代表的是整个屏幕. 但单窗口并不是任何时候都能满足人们的需求, 所以我们可以用 newwin() 来获得一个新的窗口对象 :

begin_x = 20; begin_y = 7
height = 5; width = 40
win = curses.newwin(height, width, begin_y, begin_x)

需要注意的是, 传入的第三个和第四个参数是先y再x, 这是历史遗留原因.

你可以用curses.LINEScurses.COLS 来获得你屏幕的y 和 x 大小... 同时如果你调用方法擦除屏幕的话屏幕并不会立即擦除, 必须要在你调用refresh()之后才行, 设计成这样当然也是有历史原因的, 早期的终端为了避免不必要的打印(你显示某些文字, 之后又显示另外的文字, 那么之前的文字可以直接不用显示了), 设计成了这个样子.

pad 是一个特殊的window, 他可以比实际屏幕更大, 一次只显示一部分的屏幕, 创建pad只需要高度和宽度, 但pad对象调用刷新的时候需要特别的参数 :

 pad = curses.newpad(100, 100)
# These loops fill the pad with letters; addch() is
# explained in the next section
for y in range(0, 99):
for x in range(0, 99):
pad.addch(y,x, ord('a') + (x*x+y*y) % 26) # Displays a section of the pad in the middle of the screen.
# (0,0) : coordinate of upper-left corner of pad area to display.
# (5,5) : coordinate of upper-left corner of window area to be filled
# with pad content.
# (20, 75) : coordinate of lower-right corner of window area to be
# : filled with pad content.
pad.refresh( 0,0, 5,5, 20,75)

如果你有许多的窗口对象(都需要刷新), 为了避免不必要的闪烁, 你可以先对各个需要刷新的窗口调用 noutrefresh(), 它将升级内在的数据结构使之匹配你所要的内容, 然后统一调用 doupdate() 来刷新屏幕.

显示文本 :

C语言中的curses库中有很多关于文本打印的函数, 功能上只有细微的区别, 这导致该库显得凌乱而复杂,  在python中这些函数被封装在 addstr() 这个函数中, 该函数有4种形式, 参数以及用法如图 :

Form Description
str or ch Display the string str or character ch at the current position
str or chattr Display the string str or character ch, using attribute attr at the current position
yxstr or ch Move to position y,x within the window, and display str or ch
yxstr or chattr Move to position y,x within the window, and display str or ch, using attribute attr

attr 可以用来指定显示文本的粗体, 斜体, 反向以及颜色等等, 之后会具体解释... 该函数接受一个string 或者 bytesstring, 然后使用窗口的encoding属性编码成bytes,  encoding属性默认为系统编码, 可以用 locale.getpreferredencoding() 来查询, 我的返回值是utf-8.

addch()接受一个长度为1的string或者bytesstring 或者一个整数. 指的注意的是该函数中整数超出255的将作为拓展字符, 例如 :

stdscr.addch(curses.ACS_PLMINUS)
stdscr.addch(curses.ACS_ULCORNER) # >>> ±┌

每一次操作完, 窗口对象都会记住光标上次操作的位置, 你也可以是使用move(y, x)来移动光标, 同时你可以使用 curses.curs_set(False)来关闭光标显示,  在一些较为古老的curses的版本中, 也用 leaveok(bool)达到相同的效果. (亲测无效...)

属性与颜色 :

属性和颜色可以以不同的方式显示出来, 属性可以是一个值或者是一个集合(不知道怎么弄成一个集合的形式), 但并不能保证所有的效果都能成功的表现出来, 这取决于你的终端, 下面是一些相对来说比较保险的属性...

Attribute Description
A_BLINK Blinking text
A_BOLD Extra bright or bold text
A_DIM Half bright text
A_REVERSE Reverse-video text
A_STANDOUT The best highlighting mode available
A_UNDERLINE Underlined text

比如这样你可以显示出一个类似vim状态栏的东西 :

 stdscr.addstr(0, 0, "Current mode: Typing mode",
curses.A_REVERSE)
stdscr.refresh()

为了使用不同的颜色, 你必须在调用 initscr() 之后调用 start_color(), 当然如果你使用的是 curses.wrapper(), 那么这个函数会自动地调用, 一旦这些完成了, 你可以调用has_colors()函数来确认你的是否的你的终端可以表现颜色(可以的话将返回True), 库中有多对颜色对, 每一对中都有对应的前景色和背景色, 你可以使用得到相应的颜色属性通过 color_pair() 函数, 你可以用 bitwise-or 与其他属性比如A_REVERSE 一起使用, 但不确保一定有效.

stdscr.addstr("Pretty text", curses.color_pair(1))
stdscr.refresh()

就像之前说过的, 每一个颜色对都有前景色和背景色, 我们可以用 init_pair(n, f, b) 来改变第n个颜色对的颜色, 当然第0对是无法改写的, 它将黑色写在白色的背景上. start_color() 初始化8中基本的颜色, 他们分别是 : 0:black, 1:red, 2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white.  在curses这些颜色常数被定义为了curses.COLOR_BLACKcurses.COLOR_RED ...

curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE)
#When you change a color pair, any text already displayed using that color pair
#will change to the new colors. You can also display new text in this color with:
stdscr.addstr(0,0, "RED ALERT!", curses.color_pair(1))

用户输入 :

C语言的curses库只是提供了非常简单的输入方法, 在python中这个模块加上了一个基本文本输入的玩意(widget 实在不知道怎么翻译了...) , 简单来说有2种 :

1. getch()  刷新屏幕等待用户敲击一个键, 然后如果echo() 之前被调用过得话, 这个键将被显示在屏幕上, 你也可以选择具体设置一个坐标作为光标应该移动的位置.

2. getkey() 做基本相同的事除了它返回的是字符串而不是int, 单字符返回单字符字符串, 特殊字符比如功能键返回更长的字符串包含这个按键的名字比如 'KEY_UP'或者'^G'...

当然用户可以调用 nodelay() 在调用 nodelay(True)之后, getch() 和 getkey() 在这个窗口变成了非堵塞, 如果没有输入字符已经准备好, 那么 getch() 将返回 curses.ERR(-1) getkey() 将抛出异常, 也有一个 halfdelay() 函数, 他可以作为一个计时器使用, 这使得getch()具有如下特征 : 如果在给定时间内没有输入的话, 抛出异常... (时间的单位是十分之一秒)... (我试验的结果是返回-1而不是抛出异常), 而且这个东西是curses的一个方法而不是窗口对象的方法, 它其实是开启了一种模式, 和cbreak一样, 但是有一个等待时间.

getch()一般来讲会返回一个0到255的整数这代表你按下的键相对于的ascii码, 大于255的一般是上下左右的功能键(curses.KEY_PPAGEcurses.KEY_HOME, or curses.KEY_LEFT.) :

while True:
c = stdscr.getch()
if c == ord('p'):
PrintDocument()
elif c == ord('q'):
break # Exit the while loop
elif c == curses.KEY_HOME:
x = y = 0

还有一段关于curses.ascii的, 感觉不是很重要就不翻译了, 原文 :

The curses.ascii module supplies ASCII class membership functions that take either integer or 1-character string arguments; these may be useful in writing more readable tests for such loops. It also supplies conversion functions that take either integer or 1-character-string arguments and return the same type. For example, curses.ascii.ctrl() returns the control character corresponding to its argument.

然后还有一个区的字符串的方法是 getstr(), 用的不是很多, 因为他只支持退格和回车两个编辑键位, 退格用来退格, 回车用来表示输入完毕, 下例的意思是只能输入一个小于等于15个字符的字符串, 光标从(0, 0)开始.

curses.echo()            # Enable echoing of characters

# Get a 15-character string, with the cursor on the top line
s = stdscr.getstr(0,0, 15)

curses.textpad 模块提供一个文本箱子, 支持形如emacs的键位绑定 :

import curses
from curses.textpad import Textbox, rectangle def main(stdscr):
curses.use_default_colors()
stdscr.addstr(0, 0, "Enter IM message: (hit Ctrl-G to send)") editwin = curses.newwin(5,30, 2,1)
rectangle(stdscr, 1,0, 1+5+1, 1+30+1)
stdscr.refresh() box = Textbox(editwin) # Let the user edit until Ctrl-G is struck.
box.edit() # Get resulting contents
message = box.gather() curses.wrapper(main)

这只是python的HOWTO指南, 很加详细的信息可以直接看 https://docs.python.org/3.5/library/curses.html#module-curses ... 看了几个小时终于看完了...

终端开发补充 : 读 curses模块官方文档...的更多相关文章

  1. 第0001题 : 产生随机数(顺便读random模块官方文档)

    看这个之前我准备先看一下random模块的官方文档... 在整个随机模块中,  最基础的就是random, 它产生一个 [0.0, 1.0)的浮点数. 这个模块下所有的函数实际上是绑定在一个叫做ran ...

  2. App开发架构指南(谷歌官方文档译文)

    这篇文章面向的是已经掌握app开发基本知识,想知道如何开发健壮app的读者. 注:本指南假设读者对 Android Framework 已经很熟悉.如果你还是app开发的新手,请查看 Getting ...

  3. 我为什么要翻译ES6官方文档

    ES6出来很久了,现在网上也有很多教程,其中以阮一峰老师的教程最为经典.大家通过学习阮老师的教程肯定能学懂ES6最新的技术. ES6官方文档是一个规范,各浏览器在实现ES6的具体API时都会遵循它.我 ...

  4. 【pytest官方文档】解读- 开发可pip安装的第三方插件

    在上一篇的 hooks 函数分享中,开发了一个本地插件示例,其实已经算是在编写插件了.今天继续跟着官方文档学习更多知识点. 一个插件包含一个或多个钩子函数,pytest 正是通过调用各种钩子组成的插件 ...

  5. Kotlin开发语言文档(官方文档)-- 目录

    开始阅读Kotlin官方文档.先上文档目录.有些内容还未阅读,有些目录标目翻译还需琢磨琢磨.后续再将具体内容的链接逐步加上. 文档链接:https://kotlinlang.org/docs/kotl ...

  6. iOS开发官方文档汇总

    程序员的学习过程是无止境的,程序员学习的途径是多样的.可以从视频教程中领悟,也可以从他人的代码中 理解.但当我们专注于某一个平台在开发的时候,对于某个API使用或者功能实现有疑问,通常简单的测试可以让 ...

  7. [dpdk] 读官方文档(1)

    前提:已读了这本书<<深入浅出dpdk(朱清河等著)>>. 目标:读官方文档,同时跟着文档进行安装编译等工作. http://dpdk.org/doc/guides/index ...

  8. citus 多租户应用开发(来自官方文档)

      citus 官方文档很不错,资料很全,同时包含一个多租户应用的文档,所以运行下,方便学习 环境准备 使用docker-compose 运行,同时集成了graphql 引擎,很方便 docker-c ...

  9. python附录-re.py模块源码(含re官方文档链接)

    re模块 python官方文档链接:https://docs.python.org/zh-cn/3/library/re.html re模块源码 r"""Support ...

随机推荐

  1. Django + Apache + wsgi配置和环境搭建(ubuntu)

    上一篇写了Django + nginx + uwsgi配置和环境搭建(ubuntu) 由于公司服务器环境问题,又配置了apache的环境.记录例如以下: 一. 安装环境: #apache sudo a ...

  2. springMVC中前台ajax传json数据后台controller接受对象为null

    在jquery的ajax中,如果没加contentType:"application/json",那么data就应该对应的是json对象,反之,如果加了contentType:&q ...

  3. iOS项目中所有icon的尺寸以及命名

    一般icon以下几个: Icon.png – 57×57 iPhone (ios5/6) Icon@2x.png – 114×114 iPhone Retina (ios5/6) Icon-72.pn ...

  4. 设置storyboard拉伸属性

  5. wpf SnapsToDevicePixels

    原文:wpf SnapsToDevicePixels  可以在您的根元素上将此属性设为 true,以在整个 UI 上启用像素对齐呈现. 对于运行在大于 96 每英寸点数 (dpi) 的设备,像素对 ...

  6. matlab 图像分块及恢复

    1. block_divide % 返回的块向量构成的矩阵,其维度信息为 K^2 * N,每一列由块构成的列向量 function P = block_divide(I, K) r = size(I, ...

  7. IIS执行原理

    IIS执行原理   服务器的监听(IIS6.0+版本) 当请求到达服务器时,请求最终会到达TCPIP.SYS驱动程序,TCPIP.SYS将请求转发给HTTP.SYS网络驱动程序的请求队列中(可以理解为 ...

  8. Node child_process Study.2

    child_process 模块用于新建子进程.子进程的运行结果存储在系统缓存之中,等到子进程运行结束之后,主进程再用回调函数读取子进程的运行结果 1.exec() exec 方法用于执行base命令 ...

  9. JieBaNet+Lucene.Net

    基于JieBaNet+Lucene.Net实现全文搜索   实现效果: 上一篇文章有附全文搜索结果的设计图,下面截一张开发完成上线后的实图: 基本风格是模仿的百度搜索结果,绿色的分页略显小清新. 目前 ...

  10. Android-apktool反汇编异常-Input file (XXX) was not found or was not readable.

    问题描述: 原因: 在apptool 2.0以后命令发生了变化,不能再使用 apktool d <apk_path> <outfile_path> 解决方法:解决方法: 使用命 ...