Python Curses 处理窗口(终端)调整大小

Posted

技术标签:

【中文标题】Python Curses 处理窗口(终端)调整大小【英文标题】:Python Curses Handling Window (Terminal) Resize 【发布时间】:2011-07-06 21:38:43 【问题描述】:

这真的是两个问题:

如何调整 curses 窗口的大小,以及 如何处理 curses 中的终端调整大小?

是否可以知道窗口何时改变大小?

我真的找不到任何好的文档,甚至在 http://docs.python.org/library/curses.html 上都没有介绍

【问题讨论】:

【参考方案1】:

这对我有用 curses.wrapper():

if stdscr.getch() == curses.KEY_RESIZE:
    curses.resizeterm(*stdscr.getmaxyx())
    stdscr.clear()
    stdscr.refresh()

【讨论】:

我在 VS Code 中使用终端尝试了这个,很可能是因为无限重复 curses.KEY_RESIZE 事件而陷入循环。致电curses.flushinp() 没有帮助。可惜……不过,这个答案对我的帮助最大。 @qdbp 无限重复curses.KEY_RESIZE 事件? ? 如果你不能依赖stdscr.getch(),我想你只需要跟踪stdscr.getmaxyx() 何时返回新值。【参考方案2】:

我使用来自here的代码。

在我的 curses-script 中,我不使用 getch(),所以我无法对 KEY_RESIZE 做出反应。

因此脚本对SIGWINCH 做出反应,并在处理程序中重新初始化curses 库。当然,这意味着您必须重新绘制所有内容,但我找不到更好的解决方案。

一些示例代码:

from curses import initscr, endwin
from signal import signal, SIGWINCH
from time import sleep

stdscr = initscr()

def redraw_stdscreen():
    rows, cols = stdscr.getmaxyx()
    stdscr.clear()
    stdscr.border()
    stdscr.hline(2, 1, '_', cols-2)
    stdscr.refresh()

def resize_handler(signum, frame):
    endwin()  # This could lead to crashes according to below comment
    stdscr.refresh()
    redraw_stdscreen()

signal(SIGWINCH, resize_handler)

initscr()

try:
    redraw_stdscreen()

    while 1:
        # print stuff with curses
        sleep(1)
except (KeyboardInterrupt, SystemExit):
    pass
except Exception as e:
    pass

endwin()

【讨论】:

在信号处理程序中调用 endwin/initscr 是获取核心转储的好方法。 @ThomasDickey 感谢您提供信息。我已经从信号处理程序中删除了一个 initscr() ,这可能并没有太大改善。 accepted answer 中的 c 代码建议使用 endwin() 后跟 refresh()。我是对的,python3 会通知用户有关 coredump 的信息吗?如果是的话,我到现在还没有一个,同时我还在疯狂地调整我的终端。【参考方案3】:

我让我的 python 程序通过做几件事来重新调整终端的大小。

# Initialize the screen
import curses

screen = curses.initscr()

# Check if screen was re-sized (True or False)
resize = curses.is_term_resized(y, x)

# Action in loop if resize is True:
if resize is True:
    y, x = screen.getmaxyx()
    screen.clear()
    curses.resizeterm(y, x)
    screen.refresh()

在编写程序时,我可以看到将屏幕放入它自己的类中并定义所有这些函数的有用性,因此我所要做的就是调用Screen.resize(),它会处理其余的事情。

【讨论】:

您能否添加使此代码自包含所需的任何内容?例如,我不确定“屏幕”是什么。 @DonHatch 希望这就是您想要的。如果你想要的话,这里也有一个很好的小教程。 docs.python.org/3/howto/curses.html 他的意思是,如果您只是复制并过去测试它,您的代码将无法工作,因为缺少很多东西。 您在resize = curses.is_term_resized(y, x) 中将y, x 带到哪里?是旧尺寸吗?如果是这样,您如何获得终端尺寸?对我来说,screen.getmaxyx() 似乎没有返回更新后的大小。当我改变命令行的大小时,它仍然是一样的......【参考方案4】:

这是不对的。这是一个ncurses-only 扩展名。这个问题是关于curses。要以符合标准的方式执行此操作,您需要自己捕获 SIGWINCH 并安排重绘屏幕。

【讨论】:

这里说的是 Python 的 curses 库,它实际上包装了 ncurses 库。【参考方案5】:

终端调整大小事件将产生curses.KEY_RESIZE 键码。因此,您可以在 curses 程序中将终端调整大小作为标准主循环的一部分来处理,等待getch 的输入。

【讨论】:

这是对的,但仅当 ncurses 使用 --enable-sigwinch 编译时。特别是 Debian 和 Ubuntu 中的 libncurses 没有打开它。我不知道为什么。 @thepaul:至少在我的 Ubuntu 12.04 中,当我调整终端模拟器窗口的大小时,我确实得到了curses.KEY_RESIZE 代码。 很好,很高兴他们解决了这个问题。

以上是关于Python Curses 处理窗口(终端)调整大小的主要内容,如果未能解决你的问题,请参考以下文章

推荐3个Python 文本终端 GUI 框架,太酷了

Setupterm 找不到终端,在 Python 程序中使用 curses

终端开发补充 : 读 curses模块官方文档...

Python Curses

Python Curses

是否可以在 python 中使用 curses 获取默认背景颜色?