2017-07-25 84 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