【问题标题】:Python's curses module does not refresh pad until first character receivedPython curses 模块在收到第一个字符之前不会刷新 pad
【发布时间】:2014-10-05 18:31:30
【问题描述】:

我有以下代码,可让您上下滚动一段文本。每次滚动(即处理用户输入)时,pad 都会按预期更新。然而,在按下第一个键之前,什么都没有显示,尽管我正在调用 pad.refresh(),就像我在每次用户输入之后所做的那样。

我的代码如下所示:

def main(self,stdscr):

    x,y = 20,150 # size of the window
    u,a = 10,20 # where to place window - up,across
    pad = curses.newpad(20,150) # nlines, ncols
    pad_pos = 0
    exit = False

    pad.addstr(0,0,str(self.all_results))

    while not exit:
        pad.addstr(0,0,str(self.format_results()))
        ++ stdscr.refresh()
        pad.refresh(pad_pos,10, u,a, x,y)

        -- cmd = stdscr.getch()
        ++ cmd = pad.getch()

        stdscr.nodelay(1)

        + pad.getch() - caused the screen not to update
        + stdscr.refresh() - no change

        if cmd != -1:
            + pad.getch() - - caused the screen not to update
            if  cmd == curses.KEY_DOWN:
                if pad_pos < 3:
                    pad_pos += 1
                try:
                    pad.refresh(pad_pos,0, u,a, x,y)
                except curses.error:
                    pass
            elif cmd == curses.KEY_UP:
                if pad_pos != 0:
                    pad_pos -= 1
                try:
                    pad.refresh(pad_pos,0, u,a, x,y)
                except curses.error:
                    pass

编辑:代码中显示的更改已尝试的内容(+、++、--)

【问题讨论】:

  • 第一个答案不能解决问题吗?或者你错过了什么。接受吗?

标签: python curses python-curses


【解决方案1】:

似乎有必要(AFAIK 未记录)刷新 stdscr 一次,即调用 stdscr.refresh(),然后一切都按预期工作。我将其合并到您的示例中(我以前必须进行工作 - 见下文):

import curses

def main(stdscr):
    stdscr.keypad(True)
    stdscr.refresh() # This is the necessary initial refresh

    heigth, width = 20, 150 # size of the pad
    top, left = 10, 20 # where to place pad
    viewportHeight = 10
    scrollOffset = 0

    # generate a string to fill pad
    string = ''.join(chr(ord('a') + (x % 26)) for x in range(heigth*width-1))

    pad = curses.newpad(heigth, width)
    pad.addstr(string)
    pad.refresh(scrollOffset, 0, top, left, top + 10, left + width)

    cmd = stdscr.getch()
    while True:
        if  cmd == curses.KEY_DOWN and scrollOffset < heigth - viewportHeight - 1:
            scrollOffset += 1
        elif cmd == curses.KEY_UP and scrollOffset > 0:
            scrollOffset -= 1
        if cmd:
            pad.refresh(scrollOffset, 0, top, left, top + 10, left + width)
        cmd = stdscr.getch()

curses.wrapper(main)

希望这能解决你的问题!

几点说明:

  • 对于未来,我建议您使用curses.wrapper(main)-函数来设置curses 环境并使用stdscr 作为参数调用您的main(stdscr) 方法。它还注意适当地拆除诅咒,如果您的代码出现问题,这可以防止终端损坏。也许您想查看有用的 tutorial by Kuchling and Raymond 以了解如何使用 python curses 包。

  • 请提供一个可重现的例子。您的包含变量,例如self.all_result,我必须在其中进行猜测才能理解您的问题。事实上,我花了更多的时间弄清楚你的代码试图准确实现什么并重现你描述的错误行为,而不是找到实际的解决方案。

如果您编辑您的问题以将其归结为实际问题 - 我认为这可能对许多使用 Python 的 curses 模块的人非常有帮助。

感谢和快乐的黑客;)

编辑:我刚刚意识到你提供了一个赏金来获取来自官方来源的回复,所以我挖了一点,发现an equivalent response on SO,这也表明,这 - 让我们打电话它的错误 - 到目前为止没有记录。对于进行一些 libncurses 研究的原因,我最好的猜测是,在我的情况下,curses.wrapper 是您手动的,甚至 libnurses 本身在初始化期间的任何时候都称为clear screen method。因此,可能会设置清除标志,从而在第一次刷新时清除屏幕,而不是预期的行为。

【讨论】:

  • 我相信这将适用于不经常变化的字符串。但是我使用的字符串会不断更新。
  • 在测试了所有这些之后,下面的答案解决了我的问题。不过感谢您提供的所有信息,非常感谢。
【解决方案2】:

stdscr.getch() 导致stdscr 的隐式刷新(在此之前未更新),这会通过用空白stdscr 覆盖屏幕上的pad 来擦除它。试试pad.getch(),或者在第一个pad.refresh()之前刷新stdscr

【讨论】:

  • 我尝试了这些建议,但我仍然面临同样的问题。
  • 如果您尝试了这些建议,从上面编辑的代码中看不到。
  • 这些行不是之前第一次调用pad.refresh()。此外,pad.getch() 的预期用途是将cmd = stdscr.getch() 替换为cmd = pad.getch(),而不仅仅是在您已经调用stdscr.getch() 之后继续调用pad.getch()
  • 我还添加了您提到的基于 ++ 的更改——但仍然没有任何乐趣。你总是可以用你认为代码的外观来更新你的答案:-)
【解决方案3】:

在挂断stdscr.getch() 之前,请尝试拨打stdscr.nodelay(1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-02
    • 2015-04-09
    • 2018-08-12
    • 2019-12-16
    • 1970-01-01
    • 2020-05-10
    • 2023-03-11
    • 1970-01-01
    相关资源
    最近更新 更多