如何在python curses modu中删除子窗口

2024-04-29 16:18:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个使用子窗口的curses应用程序,但我似乎无法删除它们。在

例如,此代码不起作用:

import curses
def fill(window, ch):
    y, x = window.getmaxyx()
    s = ch * (x - 1)
    for line in range(y):
        window.addstr(line, 0, s)

def main(stdscr):
    fill(stdscr, 'M')
    stdscr.refresh()
    stdscr.getch()

    subwin = stdscr.subwin(1, 28, 20, 13)
    fill(subwin, 'J')
    subwin.refresh()
    subwin.getch()

    del subwin
    stdscr.touchwin()
    stdscr.refresh()
    stdscr.getch()

curses.wrapper(main)

当您运行这段代码时,屏幕上会填充“M”,然后当您按下某个键时,就会创建一个子窗口并用“J”填充。最后,当您再次按下某个键时,代码会删除子窗口并完全重画屏幕。然而,那些J仍然存在。在

经过一些实验,我发现调用stdscr的clear()方法将使子窗口继续运行,但我希望恢复背景的原样,而不消隐和重写。 有人知道怎么做吗?在


Tags: 代码import应用程序屏幕maindeflinech
2条回答

你使用子窗口有什么好的理由吗?如果您创建了一个新的顶层窗口,那么代码就可以正常工作了——只需将stdscr.subwin更改为{},它就可以如您所期望的那样工作了。在

我不是诅咒专家,但我相信子窗口与其父窗口共享字符缓冲区,这样对其中一个的更改也会影响另一个。所以,如果你想把一个窗口细分为逻辑区域(可能是菜单栏、主区域和状态栏),那么子窗口是有用的。但是,如果你想找一个更像对话框或弹出式菜单的东西,那么你要的就是一个全新的窗口(有它自己独立的缓冲区)。在

我找不到任何关于ncurses的明确参考资料,但man page for AIX似乎证实了这一点:

Recall that the subwindow shares its parent's window buffer. Changes made to the shared window buffer in the area covered by a subwindow, through either the parent window or any of its subwindows, affects all windows sharing the window buffer.

当然,这对ncurses来说并不是决定性的,但我找不到任何相反的东西,它似乎可以解释观察到的行为。我还做了一个粗略的实验,在你的例子中,在subwin.getch()行之后,我添加了这行:

raise Exception(stdscr.instr(20, 15, 3))

在您的示例中,我得到JJJ作为实际主窗口的内容。如果我改为使用curses.newwin()而不是stdscr.subwin()来创建窗口,那么我将得到预期的MMM。在

我不知道有多少特定的Python curses资源,但是关于ncurses的大多数标准教程和文档对于这种级别非常有用。当我不得不做一些工作的时候,this document非常有用。如果您向下滚动到“示例”部分,您将看到菜单弹出窗口是而不是子窗口-他用以下略显模糊的解释暗示了这一点:

We don't want this new window to overwrite previously written characters on the background. They should stay there after the menu closes. This is why the menu window can't be created as a subwindow of stdscr.

另外,我还记得使用stdscr和你自己的窗口可能会导致问题-the "official" ncurses introduction有{a4}关于这类事情。它还建议完全避免重叠窗口,因为它们显然容易出错,但我不记得在短期瞬态模式对话框(这是我把它们放在唯一的用途)中有任何问题。当然,仅仅因为我的简单用例没有暴露任何问题并不意味着没有任何问题。然而,在像ncurses这样复杂的事情上,我能看到保持事情尽可能简单的智慧。在

我希望这能有所帮助。正如我所说,我绝不是诅咒专家,但希望这能让你更进一步。在

这个代码有两个问题。在

首先,正如前一篇文章所指出的,子窗口与父窗口共享一个缓冲区,因此如果您想要一个完全独立的窗口,就应该使用curses.newwin()。在

第二,使用del删除窗口是有问题的,因为它依赖于引用计数/垃圾回收才能正常工作。(首先,您必须删除对窗口的所有引用才能正常工作)。在

相关问题 更多 >