python 中curses封裝了c語言的curses,把c中複雜部分簡單化,比如addstr(),mvaddstr(),mvwaddstr()合併成了一個addstr()方法。
一、語法入門
1、開啟和關閉一個curses 應用程式
在任何程式碼執行前都先要初始化curses。初始化操作就是呼叫initscr()函式,如下。該函式根據不同裝置返回一個window物件代表整個螢幕,這個window物件通常叫做stdscr,和c語言報錯一致。
1 2 |
import curses stdscr = curses.initscr() |
使用curses通常要關閉螢幕回顯,目的是讀取字元僅在適當的環境下輸出。這就需要呼叫noecho()方法
1 |
curses.noecho() |
應用程式一般是立即響應的,即不需要按回車就立即回應的,這種模式叫cbreak模式,相反的常用的模式是緩衝輸入模式。開啟立即cbreak模式程式碼如下。
1 |
curses.cbreak() |
終端經常返回特殊鍵作為一個多位元組的轉義序列,比如游標鍵,或者導航鍵比如Page UP和Home鍵 。curses可以針對這些序列做一次處理,比如curses.KEY_LEFT返回一個特殊的值。要完成這些工作,必須開啟鍵盤模式。
1 |
stdscr.keypad(1) |
關閉curses非常簡單,如下:
1 2 3 |
curses.nocbreak()#關閉字元終端功能(只有回車時才發生終端) stdscr.keypad(0) curses.echo() #開啟輸入回顯功能 |
呼叫endwin()恢復預設設定
1 |
curses.endwin() |
除錯curses時常見的問題就是curses應用程式結束後沒有重置終端到之前的狀態,把終端弄的一團糟。python中該問題經常是因為程式碼有bug,傳送異常引起的。比如鍵盤敲入字元後螢幕不回顯,這讓shell用起來非常困難。
為了避免這樣的問題,可以匯入curses.wrapper模組。這個函式做了一些初始化的工作,包括上面提到的和顏色的初始化。然後再執行你提供的函式,最後重置。而且被呼叫的函式寫在try-catch中。
2、開啟新視窗和pad
通常呼叫initscr()獲取一個window物件代表全部螢幕。但是很多程式希望劃分螢幕為幾個小的視窗,為了重繪,擦出這些工作在小視窗中獨立進行。newwin()函式就是用來新建一個新的視窗,需要給定視窗尺寸,並返回新的window物件的。
1 2 3 |
begin_x = 20; begin_y = 7 height = 5; width = 40 win = curses.newwin(height, width, begin_y, begin_x) |
注意:座標通過是先y後x。這和別的座標系統不同,但是根深蒂固,寫的時候就這樣現在改太晚嘍。
當呼叫一個方法去顯示或者擦除文字時,效果不會立即顯示。 為了減少螢幕重繪的時間,curses就先累積這些操作,用一種更有效的方式去顯示。就比如說你的程式先在視窗顯示了幾個字元,然後就清除螢幕,那就沒必要傳送初始字元了,因為它們不會被顯示。
因此,curses需要你使用refresh()函式明確指出重繪視窗。
pad
pad是window的特例。pad可以比顯示的螢幕大,一次只顯示pad的一部分。建立一個pad很簡單,只需要提供寬高即可。但是重新整理pad需要提供螢幕上顯示的部分pad的座標。
1 2 3 4 5 6 7 8 9 10 11 12 |
pad = curses.newpad(100, 100) # These loops fill the pad with letters; this is # explained in the next section for y in range(0, 100): for x in range(0, 100): try: pad.addch(y,x, ord('a') + (x*x+y*y) % 26) except curses.error: pass # Displays a section of the pad in the middle of the screen pad.refresh(0,0, 5,5, 20,75) |
同時由多個window或者多個pad,有一問題:重新整理某個window或pad時螢幕會閃爍。
避免閃爍的方法:在每個window呼叫noutrefresh()方法。 然後使用refresh()方法的最後再呼叫doupdate()方法。
3、顯示文字
addscr不同格式如下:如果沒有座標,字元顯示在上一次操作完的位置。
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 |
屬性可以讓文字高亮顯示,比如黑體,下劃線,倒序,彩色顯示。
4、屬性和顏色
屬性和描述:
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 |
螢幕第一行reverse-video顯示。
1 2 3 |
stdscr.addstr(0, 0, "Current mode: Typing mode", curses.A_REVERSE) stdscr.refresh() |
curses使用前景色和背景色,可通過color_pair()方法獲取一對顏色。
使用顏色對1顯示一行
1 2 |
stdscr.addstr("Pretty text", curses.color_pair(1)) stdscr.refresh() |
start_color()初始化了8中基本顏色:0:black, 1:red, 2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white。
init_pair(n,f,b)修改顏色對n,讓f為前景色,b為背景色。顏色對0天生的黑白色,不允許改。
比如:修改color1為紅色文字,白色背景:
1 |
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE) |
使用:
1 |
stdscr.addstr(0,0, "RED ALERT!", curses.color_pair(1)) |
5、使用者輸入
獲取輸入一遍使用getch()方法,這個方法暫停等待使用者輸入,顯示用echo()方法。
getch()返回一個整數 ,在0到255之間,表示輸入字元的ASCII值。列印255的是些特殊字元,比如Page Up,Home。
程式碼經常這樣寫
1 2 3 4 5 6 7 8 |
while 1: c = stdscr.getch() if c == ord('p'): PrintDocument() elif c == ord('q'): break # Exit the while() elif c == curses.KEY_HOME: x = y = 0 |
getstr()獲取一個字串。因為功能有限不常用。
1 2 3 |
curses.echo() # Enable echoing of characters # Get a 15-character string, with the cursor on the top line s = stdscr.getstr(0,0, 15) |
二、例子
程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
#-*- coding: UTF-8 -*- import curses stdscr = curses.initscr() def display_info(str, x, y, colorpair=2): '''''使用指定的colorpair顯示文字''' global stdscr stdscr.addstr(y, x,str, curses.color_pair(colorpair)) stdscr.refresh() def get_ch_and_continue(): '''''演示press any key to continue''' global stdscr #設定nodelay,為0時會變成阻塞式等待 stdscr.nodelay(0) #輸入一個字元 ch=stdscr.getch() #重置nodelay,使得控制檯可以以非阻塞的方式接受控制檯輸入,超時1秒 stdscr.nodelay(1) return True def set_win(): '''''控制檯設定''' global stdscr #使用顏色首先需要呼叫這個方法 curses.start_color() #文字和背景色設定,設定了兩個color pair,分別為1和2 curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) #關閉螢幕回顯 curses.noecho() #輸入時不需要回車確認 curses.cbreak() #設定nodelay,使得控制檯可以以非阻塞的方式接受控制檯輸入,超時1秒 stdscr.nodelay(1) def unset_win(): '''控制檯重置''' global stdstr #恢復控制檯預設設定(若不恢復,會導致即使程式結束退出了,控制檯仍然是沒有回顯的) curses.nocbreak() stdscr.keypad(0) curses.echo() #結束視窗 curses.endwin() if __name__=='__main__': try: set_win() display_info('Hola, curses!',0,5) display_info('Press any key to continue...',0,10) get_ch_and_continue() except Exception,e: raise e finally: unset_win() |
執行:# python testcurses.py
三、排錯
報錯:
1 2 3 4 5 6 7 |
[root@yl-web-test srv]# python curses.py Traceback (most recent call last): File "curses.py", line 2, in <module> import curses File "/srv/curses.py", line 4, in <module> stdscr = curses.initscr() AttributeError: 'module' object has no attribute 'initscr' |
原因:因為我的檔案取名是curses.py,而系統也是用的curses.py,python執行時先從當前目錄查詢,所以不能和系統檔案重名。
換個名字,比如改名為testcurses.py 就好了。
參考:
https://docs.python.org/2/howto/curses.html
請使用手機”掃一掃”x
請使用手機”掃一掃”x