如何在Python/Curses子窗口中滚动文本?
在我的Python脚本中,我使用了Curses库,并创建了一个子窗口来显示一些文本。因为文本的长度可能会超过窗口的大小,所以这些文本应该是可以滚动的。
看起来Curses窗口没有类似于CSS中“overflow”的属性。Python/Curses的文档在这方面也比较难懂。
这里有没有人知道我该如何用Python编写一个可以滚动的Curses子窗口,并实际实现滚动功能呢?
\编辑:更具体的问题
6 个回答
5
设置窗口的滚动功能为开启状态(scrollok(True))。
12
好的,我之前对如何使用“pads”(用来滚动文本)有点困惑,看了这篇帖子后还是没搞明白;尤其是我想在一个已经存在的“行数组”中使用它。所以我准备了一个小例子,展示了newpad
和subpad
之间的相似之处和不同之处:
#!/usr/bin/env python2.7
import curses
# content - array of lines (list)
mylines = ["Line {0} ".format(id)*3 for id in range(1,11)]
import pprint
pprint.pprint(mylines)
def main(stdscr):
hlines = begin_y = begin_x = 5 ; wcols = 10
# calculate total content size
padhlines = len(mylines)
padwcols = 0
for line in mylines:
if len(line) > padwcols: padwcols = len(line)
padhlines += 2 ; padwcols += 2 # allow border
stdscr.addstr("padhlines "+str(padhlines)+" padwcols "+str(padwcols)+"; ")
# both newpad and subpad are <class '_curses.curses window'>:
mypadn = curses.newpad(padhlines, padwcols)
mypads = stdscr.subpad(padhlines, padwcols, begin_y, begin_x+padwcols+4)
stdscr.addstr(str(type(mypadn))+" "+str(type(mypads)) + "\n")
mypadn.scrollok(1)
mypadn.idlok(1)
mypads.scrollok(1)
mypads.idlok(1)
mypadn.border(0) # first ...
mypads.border(0) # ... border
for line in mylines:
mypadn.addstr(padhlines-1,1, line)
mypadn.scroll(1)
mypads.addstr(padhlines-1,1, line)
mypads.scroll(1)
mypadn.border(0) # second ...
mypads.border(0) # ... border
# refresh parent first, to render the texts on top
#~ stdscr.refresh()
# refresh the pads next
mypadn.refresh(0,0, begin_y,begin_x, begin_y+hlines, begin_x+padwcols)
mypads.refresh()
mypads.touchwin()
mypadn.touchwin()
stdscr.touchwin() # no real effect here
#stdscr.refresh() # not here! overwrites newpad!
mypadn.getch()
# even THIS command erases newpad!
# (unless stdscr.refresh() previously):
stdscr.getch()
curses.wrapper(main)
当你运行这个代码时,最开始你会看到类似这样的效果(左边是newpad
,右边是subpad
):
┌────────────────────────┐ ┌────────────────────────┐
│Line 1 Line 1 Line 1 ───│ │Line 1 Line 1 Line 1 ───│
│Line 2 Line 2 Line 2 │ │Line 2 Line 2 Line 2 │
│Line 3 Line 3 Line 3 │ │Line 3 Line 3 Line 3 │
│Line 4 Line 4 Line 4 │ │Line 4 Line 4 Line 4 │
│Line 5 Line 5 Line 5 │ │Line 5 Line 5 Line 5 │
│Line 6 Line 6 Line 6 │
│Line 7 Line 7 Line 7 │
│Line 8 Line 8 Line 8 │
│Line 9 Line 9 Line 9 │
│Line 10 Line 10 Line 10 │
└────────────────────────┘
一些注意事项:
- 无论是
newpad
还是subpad
,它们的宽度和高度都应该根据内容来设置(行数和每行的最大宽度)加上可能的边框空间 - 在这两种情况下,你都可以通过
scrollok()
来允许额外的行,但不能增加宽度 - 在这两种情况下,你基本上是“推”一行到pad的底部;然后用
scroll()
向上滚动以为下一行腾出空间 newpad
有一个特殊的refresh
方法,可以让你在屏幕上显示这“整个内容”的一部分;而subpad
基本上必须以它创建时的大小显示- 如果你在添加内容字符串之前先画出pads的边框,那么边框也会一起向上滚动(这就是在
...Line 1 ───│
部分看到的───
)。
有用的链接:
34
用 window.scroll
的方法太复杂了,移动窗口里的内容不太好实现。相反,curses.newpad
就能帮我解决这个问题。
首先,创建一个新的面板:
mypad = curses.newpad(40,60)
mypad_pos = 0
mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)
然后,你可以通过根据 cmd
中的 window.getch()
输入来增加或减少 mypad_pos
的值,从而实现滚动:
if cmd == curses.KEY_DOWN:
mypad_pos += 1
mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)
elif cmd == curses.KEY_UP:
mypad_pos -= 1
mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)