2017-07-25 83 views
0

在可以處理調整大小的終端窗口底部打印一行的正確方法是什麼?Python詛咒終端調整大小問題

import curses 
from curses import wrapper 

def main(stdscr): 
    inp = 0 
    y,x = stdscr.getmaxyx() 
    stdscr.clear() 
    stdscr.nodelay(1) 
    while inp != 48 and inp != 27: 
     stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x) 
     inp = stdscr.getch() 

wrapper(main) 

一旦我調整終端到少的列,則字符串的長度它試圖換到下一行和錯誤的。我在關於禁用包裝的文檔中看不到任何東西。

我試着在addstr函數之前更新我的最大y值。

while inp != 48 and inp != 27: 

     if (y,x) != stdscr.getmaxyx(): 
      y,x = stdscr.getmaxyx() 

     stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x) 
     inp = stdscr.getch() 

我也試着捕捉SIGWINCH

while inp != 48 and inp != 27: 

     def resize_handler(signum, frame): 
      stdscr.erase() 
      stdscr.refresh() 
      termsize = shutil.get_terminal_size() 
      curses.resizeterm(termsize[1],termsize[0]) 
      y,x = stdscr.getmaxyx() 

     signal.signal(signal.SIGWINCH, resize_handler) 

     stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x) 
     inp = stdscr.getch() 

但是這些都似乎捕捉到終端更新夠早。

+0

請參考以下鏈接https://開頭的郵件.python.org/pipermail/python-list/2007-February/426098.html – Bijoy

回答

1

處理SIGWINCH對於給定的實例中的正確方式是包裹stdscr.addnstrstdscr.getch呼叫中的代碼塊,其重繪文本(限制字符到現有終端大小的數量),這樣做與終端的大小一樣多。

問題是stdscr.getch調用(實際上是ncurses中的C函數執行工作)被中斷。這是refresh這是在第一個例子中的循環執行。 ncurses'stdscr.getch應該從stdscr.getch調用中返回一個KEY_RESIZE,應用程序可以使用它來判斷何時重新繪製事物。 (這個工作除了OpenBSD由於非技術原因而忽略了這個特性)。

建立信號句柄可以防止ncurses告訴應用程序終端已調整大小。閱讀第二個例子,看起來ncurses庫仍然在等待輸入,已經完成了將addnstr文本放在屏幕上(從第一個調整大小之前)的刷新。

討論Curses and resizing windows顯示了一個錯誤:如果應用程序不會讀取字符,它將永遠不會看到KEY_RESIZE。但你的榜樣並沒有這樣做。我丟棄信號處理器(除了湊了過來,它採用信號不安全的功能,這可以打破蟒蛇),和第一例更改爲這樣的事情:

import curses 
from curses import wrapper 

def main(stdscr): 
    inp = 0 
    y,x = stdscr.getmaxyx() 
    stdscr.clear() 
    stdscr.nodelay(1) 
    while inp != 48 and inp != 27: 
     while True: 
      try: 
       stdscr.addnstr(y-1,0, 'I AM KILL TERMINAL WHEN RESIZE AAAAAAAH', x) 
      except curses.error: 
       pass 
      inp = stdscr.getch() 
      if inp != curses.KEY_RESIZE: 
       break 
      stdscr.erase() 
      y,x = stdscr.getmaxyx() 

wrapper(main) 
+0

輝煌,謝謝 – huwwp