如何在Python/Curses子窗口中滚动文本?

lec*_*tif 22 python curses scroll

在我使用Curses的Python脚本中,我有一个subwin,其中分配了一些文本.由于文本长度可能比窗口大小长,因此文本应该是可滚动的.

似乎没有任何CSS-"溢出"类似于Curses窗口的属性.Python/Curses文档在这方面也相当神秘.

这里有人知道如何使用Python编写可滚动的Curses子窗口并实际滚动它吗?

\编辑:更准确的问题

lec*_*tif 27

使用window.scroll确定它太复杂了,无法移动窗口的内容.相反,curses.newpad为我做了.

创建一个垫:

mypad = curses.newpad(40,60)
mypad_pos = 0
mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)
Run Code Online (Sandbox Code Playgroud)

然后你可以通过增加/减少mypad_pos来滚动,具体取决于cmd中window.getch()的输入:

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)
Run Code Online (Sandbox Code Playgroud)


sda*_*aau 7

是的,我对如何利用打击垫(为了滚动文本)感到有点困惑,在阅读这篇文章后仍然无法弄明白; 特别是因为我想在内容为现有"行数组"的上下文中使用它.因此,我制备了一个小例子,示出之间的相似性(和差异)newpadsubpad:

#!/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)
Run Code Online (Sandbox Code Playgroud)

当你运行它时,首先你会得到类似的东西(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 ?
                               ??????????????????????????
Run Code Online (Sandbox Code Playgroud)

一些说明:

  • 二者newpadsubpad应具有它们的宽度/高度尺寸含量(NUM线/线的阵列的最大线宽度)+最终边界空间
  • 在这两种情况下,您可以允许额外的行scrollok()- 但不是额外的宽度
  • 在这两种情况下,你基本上都"推"了垫底部的一条线; 然后scroll()为下一个腾出空间
  • 具有的特殊refresh方法newpad允许在屏幕上显示该"全部内容"的区域; subpad更多 - 必须以实例化的大小显示
  • 如果在添加内容字符串之前绘制打击垫的边框 - 那么边框也会向上滚动(即在???部件上显示的...Line 1 ????部分).

有用的链接:


san*_*koz 5

设置window.scrollok(True)。

文档

  • 这使得窗口接受超出其自身大小的文本。可以使用 window.scroll(1) 进行滚动。但是滚动的线必须重新绘制,这在文档中没有解释。因此,让 Curses 窗口滚动需要几个步骤,其中一些我仍然缺少...... (10认同)