将行打印到可以处理调整大小的终端窗口底部的正确方法是什么?
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函数之前更新我的max y,x值。
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 :(得分:3)
正确处理给定示例的 SIGWINCH
的方法是将stdscr.addnstr
和stdscr.getch
调用封装在一个块中重写文本的代码(将字符数限制为现有的终端大小),在终端调整大小时执行此操作。
问题是stdscr.getch
调用(实际上ncurses中的C函数正在执行工作)被中断。这就是在第一个例子中循环中执行的refresh
。 ncurses'stdscr.getch
应该从KEY_RESIZE
调用中返回 stdscr.getch
,应用程序可以使用它来判断何时重新绘制内容。 (除了 OpenBSD 之外,其他功能因非技术原因而忽略了该功能)。
建立信号句柄可防止ncurses告诉应用程序终端已调整大小。阅读第二个例子,似乎ncurses库仍然在等待输入,已经完成了将addnstr
文本放在屏幕上的刷新(从第一次调整大小之前)。
讨论Curses and resizing windows显示了一个陷阱:如果应用程序不会读取字符,则永远不会看到 KEY_RESIZE
。但是你的例子并没有这样做。我放弃了信号处理程序(除了妨碍它,它使用信号不安全的函数,它可以破坏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:
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)