bradical987
bradical987

Reputation: 15

Python Curses Border on Resize

I am building a simple scrollable menu in Python 2.7 with curses and trying to make it scale for any window size, including if the terminal size changes (i.e. I want it to be larger or smaller while I'm using the menu). I have a simple test code that I'm using to try and figure out this problem. It seems, if this is possible, I am really close, but what I am seeing is that when I resize my terminal window (using mRemoteNG), the border draws lines to fill in space, as seen at the bottom of the screenshot, after I extended the window vertically:

resize-test_border-lines

The code I am using to test this is as follows:

import curses
import os

VERSION = "0.1-dev" #version number

screen = curses.initscr() #initialize the curses window

#Configure color pairs for showing select menu options as highlighted
curses.start_color() #enable color for highlighting menu options
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) #color pair 1
highlightText = curses.color_pair(1) #color pair for highlighted menu option
normalText = curses.A_NORMAL #color pair for non-highlighted menu options

#Configure global variables for Curses
curses.noecho() #disable the keypress echo to prevent double input
curses.cbreak() #disable line buffers to run the keypress immediately
curses.curs_set(0)
screen.keypad(1) #enable keyboard use
screen.addstr(2, 2, "Screen Resize Test" + VERSION, curses.A_UNDERLINE)

#test screen resize
def main_screen():
    escape = False
    while escape == False:
        maxY, maxX = screen.getmaxyx()
        screen.border('|', '|', '-', '-', '+', '+', '+', '+')
        screen.addstr(4, 2, "MaxY: " + str(maxY))
        screen.addstr(5, 2, "MaxX: " + str(maxX))
        screen.refresh()

        x = screen.getch()

        if x == ord("q"):
            escape = True




main_screen()


curses.endwin() # *** CRITICAL *** this closes the curses menu and returns user to bash
os.system('clear') #clears the screen to avoid curses remnants

I've tried many different placements of screen.refresh() and screen.clear(), but it never seems to get rid of the remnants of lines at the edges of the curses window. Obviously, if this is possible, I either can't figure out where to place one/both of these or I'm not on the right track.

Upvotes: 1

Views: 7927

Answers (1)

Thomas Dickey
Thomas Dickey

Reputation: 54495

In your program, you should check for curses.KEY_RESIZE as a return value from getch, and in that case, call screen.erase.

Also, the existing call to screen.refresh is unnecessary, since screen.getch does that anyway.

This works for me:

import curses
import os

VERSION = "0.1-dev" #version number

screen = curses.initscr() #initialize the curses window

#Configure color pairs for showing select menu options as highlighted
curses.start_color() #enable color for highlighting menu options
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE) #color pair 1
highlightText = curses.color_pair(1) #color pair for highlighted menu option
normalText = curses.A_NORMAL #color pair for non-highlighted menu options

#Configure global variables for Curses
curses.noecho() #disable the keypress echo to prevent double input
curses.cbreak() #disable line buffers to run the keypress immediately
curses.curs_set(0)
screen.keypad(1) #enable keyboard use
screen.addstr(2, 2, "Screen Resize Test" + VERSION, curses.A_UNDERLINE)

#test screen resize
def main_screen():
    escape = False
    while escape == False:
        maxY, maxX = screen.getmaxyx()
        screen.border('|', '|', '-', '-', '+', '+', '+', '+')
        screen.addstr(4, 2, "MaxY: " + str(maxY))
        screen.addstr(5, 2, "MaxX: " + str(maxX))

        x = screen.getch()

        if x == ord("q"):
            escape = True
            curses.endwin()
        elif x == curses.KEY_RESIZE:
            screen.erase()
            screen.addstr(2, 2, "Screen Resize Test" + VERSION, curses.A_UNDERLINE)

main_screen()

Upvotes: 3

Related Questions