终端开发补充 : 读 curses模块官方文档...
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.LINES 和 curses.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 ch, attr | Display the string str or character ch, using attribute attr at the current position |
y, x, str or ch | Move to position y,x within the window, and display str or ch |
y, x, str or ch, attr | 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_BLACK
, curses.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_PPAGE
, curses.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模块官方文档...的更多相关文章
- 第0001题 : 产生随机数(顺便读random模块官方文档)
看这个之前我准备先看一下random模块的官方文档... 在整个随机模块中, 最基础的就是random, 它产生一个 [0.0, 1.0)的浮点数. 这个模块下所有的函数实际上是绑定在一个叫做ran ...
- App开发架构指南(谷歌官方文档译文)
这篇文章面向的是已经掌握app开发基本知识,想知道如何开发健壮app的读者. 注:本指南假设读者对 Android Framework 已经很熟悉.如果你还是app开发的新手,请查看 Getting ...
- 我为什么要翻译ES6官方文档
ES6出来很久了,现在网上也有很多教程,其中以阮一峰老师的教程最为经典.大家通过学习阮老师的教程肯定能学懂ES6最新的技术. ES6官方文档是一个规范,各浏览器在实现ES6的具体API时都会遵循它.我 ...
- 【pytest官方文档】解读- 开发可pip安装的第三方插件
在上一篇的 hooks 函数分享中,开发了一个本地插件示例,其实已经算是在编写插件了.今天继续跟着官方文档学习更多知识点. 一个插件包含一个或多个钩子函数,pytest 正是通过调用各种钩子组成的插件 ...
- Kotlin开发语言文档(官方文档)-- 目录
开始阅读Kotlin官方文档.先上文档目录.有些内容还未阅读,有些目录标目翻译还需琢磨琢磨.后续再将具体内容的链接逐步加上. 文档链接:https://kotlinlang.org/docs/kotl ...
- iOS开发官方文档汇总
程序员的学习过程是无止境的,程序员学习的途径是多样的.可以从视频教程中领悟,也可以从他人的代码中 理解.但当我们专注于某一个平台在开发的时候,对于某个API使用或者功能实现有疑问,通常简单的测试可以让 ...
- [dpdk] 读官方文档(1)
前提:已读了这本书<<深入浅出dpdk(朱清河等著)>>. 目标:读官方文档,同时跟着文档进行安装编译等工作. http://dpdk.org/doc/guides/index ...
- citus 多租户应用开发(来自官方文档)
citus 官方文档很不错,资料很全,同时包含一个多租户应用的文档,所以运行下,方便学习 环境准备 使用docker-compose 运行,同时集成了graphql 引擎,很方便 docker-c ...
- python附录-re.py模块源码(含re官方文档链接)
re模块 python官方文档链接:https://docs.python.org/zh-cn/3/library/re.html re模块源码 r"""Support ...
随机推荐
- MinGW 与MSVC的区别
Qt 中有两种方式编译,一种是MinGW ,另一种MSVC. 其中:MSVC是指微软的VC编译器 MingGW是指是Minimalist GNU on Windows的缩写.它是一个可自由使用和自由发 ...
- 【42.07%】【codeforces 558A】Lala Land and Apple Trees
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- 程序猿的还有一出路:大数据project师
非常多年前我非常郁闷地写了一篇博客<程序猿的出路在哪里?>,之所以郁闷.我记得是看了中国男足的比赛,不由自主对照自已苦逼的程序猿生涯,以前对中国软件的感情有如对中国男足,绝望到没有不论什么 ...
- Web报表工具FineReport实现EXCEL数据导入自由报表
在制作填报报表的时候.对于空白填报表,经常导出为Excel,派发给各部门人员填写后上交.怎样能避免手动输入,直接将Excel中的数据导入到填报表中提交入库呢? 这里以一个简单的员工信息填报演示样例进行 ...
- Android百日程序:GridView实现相冊效果
本章使用GridView控件来做一个相冊效果. 图片效果例如以下: 响应点击事件,点击的时候提示是当前第几章图片.从左到右,从上到下. 点击了第一张图片,显示了1. 步骤: 一 新建项目,然后把图片资 ...
- php 获取提交来源,判断从哪里提交的
echo $_SERVER['HTTP_REFERER'];这个获取上个页面的url例如获得的是 $url = http://www.weisuyun.com/nihao.html其他页面提交过来的不 ...
- 删除vector中的重复数据(unique)
#include <iostream> #include <vector> #include <algorithm> #include <assert.h&g ...
- js匿名自执行函数
匿名自执行函数:没有方法名的函数闭包:闭包是指有权访问另一个函数作用域变量的函数: 通过一个实例来解释: 从网上找到了一个案例,使用了for循环.匿名自执行函数.setTimeout. 案例1: va ...
- js进阶 10-8 伪类选择器有哪几类(自己不用,永远不是自己的)
js进阶 10-8 伪类选择器有哪几类(自己不用,永远不是自己的) 一.总结 一句话总结:自己不用,永远不是自己的. 0.学而不用,却是为何? 自己不用,永远不是自己的,有需求的时候要想到它,然后操作 ...
- html5--6-33 CSS定位是什么
html5--6-33 CSS定位是什么 一.总结 一句话总结: 1.常规文档流是一套体系,浮动是另外一套体系. 2.标签清除浮动之后会跑到常规文档流它本来的地方. 3.浮动是否占据常规文档流:应该不 ...