Python的curses模块在接收第一个字符前不刷新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
补充说明:代码中显示了我尝试过的修改(+,++,--)
3 个回答
stdscr.getch()
这个命令会自动刷新 stdscr
(在这之前没有更新),结果就是把屏幕上的 pad
给覆盖掉了,变成了空白的 stdscr
。你可以试试用 pad.getch()
,或者在第一次使用 pad.refresh()
之前先刷新一下 stdscr
。
看起来在使用标准屏幕(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)
方法。这个函数还会在你的代码出错时,妥善处理 curses,避免终端出现问题。你可以看看 Kuchling 和 Raymond 的教程,了解如何使用 Python 的 curses 包。请提供一个可复现的例子。你的例子里有像
self.all_result
这样的变量,我不得不猜测才能理解你的问题。实际上,我花了更多时间去弄清楚你的代码到底想实现什么,以及复现你描述的错误行为,而不是找到实际的解决方案。
如果你能编辑你的问题,聚焦在实际问题上,我觉得这对很多使用 Python 的 curses 模块的人会很有帮助。
我刚发现你为官方来源的回复提供了悬赏,所以我又多查了一下,发现了 一个在 SO 上的类似回复,也提到这个 - 我们可以称之为 bug - 目前没有文档说明。根据我对 libncurses 的研究,我猜测可能是因为在我的情况下,curses.wrapper
手动调用了一个 清屏方法,在初始化的某个时刻。因此,清屏标志可能被设置了,这样在第一次刷新时就会清空屏幕,而不是我们预期的行为。
试着在你挂断 stdscr.getch()
之前,先调用 stdscr.nodelay(1)
。