How to scroll text in Python/Curses subwindow?

后端 未结 5 2014
陌清茗
陌清茗 2021-01-30 23:01

In my Python script which uses Curses, I have a subwin to which some text is assigned. Because the text length may be longer than the window size, the text should be scrollable.

5条回答
  •  [愿得一人]
    2021-01-30 23:45

    Right, I was a bit confused on how to utilize pads (in order to scroll text), and still couldn't figure it out after reading this post; especially since I wanted to use it in a context of the content being an existing "array of lines". So I prepared a small example, that shows similarities (and differences) between newpad and 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 :
      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)
    

    When you run this, at first you will get something like (newpad left, subpad right):

     ┌────────────────────────┐    ┌────────────────────────┐
     │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 │
                                   └────────────────────────┘
    

    Some notes:

    • Both newpad and subpad should have their width/height sized to the content (num lines/max line width of the array of lines) + eventual border space
    • In both cases, you could allow extra lines with scrollok() - but not extra width
    • In both cases, you basically "push" a line at the bottom of the pad; and then scroll() up to make room for the next
    • The special refresh method that newpad has, then allows for just a region of this "whole content" to be shown on screen; subpad more-less has to be shown in the size it was instantiated in
    • If you draw the borders of the pads before adding content strings - then the borders will scroll up too (that is the ─── piece shown at the ...Line 1 ───│ part).

    Useful links:

    • (n)curses pad in python not working
    • http://threeseas.net/vic/vic/terminal.py
    • How do I delete a curse window in python and restore background window?

提交回复
热议问题