scroll page by page or line by line using python curses

后端 未结 2 1757
天涯浪人
天涯浪人 2021-01-25 16:11

Using python curses I am trying to write some text in to window. But when I reach end of window i get addstr() returned ERR

how to scroll the output page by

相关标签:
2条回答
  • 2021-01-25 16:37

    This is the answer to: How to make a scrolling menu in python-curses

    This code allows you to create a little menu in a box from a list of strings.
    You can also use this code getting the list of strings from a sqlite query or from a csv file.
    To edit the max number of rows of the menu you just have to edit max_row.
    If you press enter the program will print the selected string value and its position.

    from __future__ import division  #You don't need this in Python3
    import curses
    from math import *
    
    
    
    screen = curses.initscr()
    curses.noecho()
    curses.cbreak()
    curses.start_color()
    screen.keypad( 1 )
    curses.init_pair(1,curses.COLOR_BLACK, curses.COLOR_CYAN)
    highlightText = curses.color_pair( 1 )
    normalText = curses.A_NORMAL
    screen.border( 0 )
    curses.curs_set( 0 )
    max_row = 10 #max number of rows
    box = curses.newwin( max_row + 2, 64, 1, 1 )
    box.box()
    
    
    strings = [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n" ] #list of strings
    row_num = len( strings )
    
    pages = int( ceil( row_num / max_row ) )
    position = 1
    page = 1
    for i in range( 1, max_row + 1 ):
        if row_num == 0:
            box.addstr( 1, 1, "There aren't strings", highlightText )
        else:
            if (i == position):
                box.addstr( i, 2, str( i ) + " - " + strings[ i - 1 ], highlightText )
            else:
                box.addstr( i, 2, str( i ) + " - " + strings[ i - 1 ], normalText )
            if i == row_num:
                break
    
    screen.refresh()
    box.refresh()
    
    x = screen.getch()
    while x != 27:
        if x == curses.KEY_DOWN:
            if page == 1:
                if position < i:
                    position = position + 1
                else:
                    if pages > 1:
                        page = page + 1
                        position = 1 + ( max_row * ( page - 1 ) )
            elif page == pages:
                if position < row_num:
                    position = position + 1
            else:
                if position < max_row + ( max_row * ( page - 1 ) ):
                    position = position + 1
                else:
                    page = page + 1
                    position = 1 + ( max_row * ( page - 1 ) )
        if x == curses.KEY_UP:
            if page == 1:
                if position > 1:
                    position = position - 1
            else:
                if position > ( 1 + ( max_row * ( page - 1 ) ) ):
                    position = position - 1
                else:
                    page = page - 1
                    position = max_row + ( max_row * ( page - 1 ) )
        if x == curses.KEY_LEFT:
            if page > 1:
                page = page - 1
                position = 1 + ( max_row * ( page - 1 ) )
    
        if x == curses.KEY_RIGHT:
            if page < pages:
                page = page + 1
                position = ( 1 + ( max_row * ( page - 1 ) ) )
        if x == ord( "\n" ) and row_num != 0:
            screen.erase()
            screen.border( 0 )
            screen.addstr( 14, 3, "YOU HAVE PRESSED '" + strings[ position - 1 ] + "' ON POSITION " + str( position ) )
    
        box.erase()
        screen.border( 0 )
        box.border( 0 )
    
        for i in range( 1 + ( max_row * ( page - 1 ) ), max_row + 1 + ( max_row * ( page - 1 ) ) ):
            if row_num == 0:
                box.addstr( 1, 1, "There aren't strings",  highlightText )
            else:
                if ( i + ( max_row * ( page - 1 ) ) == position + ( max_row * ( page - 1 ) ) ):
                    box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + strings[ i - 1 ], highlightText )
                else:
                    box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + strings[ i - 1 ], normalText )
                if i == row_num:
                    break
    
    
    
        screen.refresh()
        box.refresh()
        x = screen.getch()
    
    curses.endwin()
    exit()
    

    Screenshot of the code

    0 讨论(0)
  • 2021-01-25 16:46

    The problem is that your calls to screen.addstr have asked for a line number past the end of the screen. Taking into account the box which you have drawn on the screen, a better approach would be to create a new window just inside the box (using curses.newwin for example) and write the addstr calls within that window.

    Your example does not compile as given. Here is a working example:

    import curses
    import logging
    import subprocess
    import sys
    
    command = "ls -l /bin"
    try:
        screen = curses.initscr()
        screen.immedok(True)
        curses.start_color()
        curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)
        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)
        screen.bkgd(curses.color_pair(2))
        screen.border(0)
        boxed = curses.newwin(curses.LINES - 2, curses.COLS - 2, 1, 1)
        boxed.scrollok(1)
    
        p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        (output, err) = p.communicate()
        linenumber = 1
        for line in output.split("\n"):
            if linenumber <= 2:
                # First two lines are header, mark bold
                boxed.addstr(line, curses.color_pair(1)|curses.A_BOLD)
            else:
                boxed.addstr(line)
            boxed.addch("\n")
            linenumber += 1
            boxed.getch()
    
        screen.getch()
        curses.endwin()
    
    except Exception, e:
        print "\n\033[1;91m[FAILED]\033[0m  Interrupt  ", e
        logging.error(e, exc_info=True)
    
    0 讨论(0)
提交回复
热议问题