Python Curses Handling Window (Terminal) Resize

Question:

This is two questions really:

  • how do I resize a curses window, and
  • how do I deal with a terminal resize in curses?

Is it possible to know when a window has changed size?

I really can’t find any good doc, not even covered on http://docs.python.org/library/curses.html

Asked By: Pez Cuckow

||

Answers:

Terminal resize event will result in the curses.KEY_RESIZE key code. Therefore you can handle terminal resize as part of a standard main loop in a curses program, waiting for input with getch.

Answered By: Michael McLoughlin

It isn’t right. It’s an ncurses-only extension. The question asked about curses. To do this in a standards-conforming way you need to trap SIGWINCH yourself and arrange for the screen to be redrawn.

Answered By: user3237013

I got my python program to re-size the terminal by doing a couple of things.

# Initialize the screen
import curses

screen = curses.initscr()

# Check if screen was re-sized (True or False)
resize = curses.is_term_resized(y, x)

# Action in loop if resize is True:
if resize is True:
    y, x = screen.getmaxyx()
    screen.clear()
    curses.resizeterm(y, x)
    screen.refresh()

As I’m writing my program I can see the usefulness of putting my screen into it’s own class with all of these functions defined so all I have to do is call Screen.resize() and it would take care of the rest.

Answered By: jarsever

I use the code from here.

In my curses-script I don’t use getch(), so I can’t react to KEY_RESIZE.

Therefore the script reacts to SIGWINCH and within the handler re-inits the curses library. That means of course, you’ll have to redraw everything, but I could not find a better solution.

Some example code:

from curses import initscr, endwin
from signal import signal, SIGWINCH
from time import sleep

stdscr = initscr()

def redraw_stdscreen():
    rows, cols = stdscr.getmaxyx()
    stdscr.clear()
    stdscr.border()
    stdscr.hline(2, 1, '_', cols-2)
    stdscr.refresh()

def resize_handler(signum, frame):
    endwin()  # This could lead to crashes according to below comment
    stdscr.refresh()
    redraw_stdscreen()

signal(SIGWINCH, resize_handler)

initscr()

try:
    redraw_stdscreen()

    while 1:
        # print stuff with curses
        sleep(1)
except (KeyboardInterrupt, SystemExit):
    pass
except Exception as e:
    pass

endwin()
Answered By: JackLeEmmerdeur

This worked for me when using curses.wrapper():

if stdscr.getch() == curses.KEY_RESIZE:
    curses.resizeterm(*stdscr.getmaxyx())
    stdscr.clear()
    stdscr.refresh()
Answered By: Mike Conigliaro
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.