Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete a subwindow in the python curses module

Tags:

python

curses

I've got a curses application that uses subwindows, but I can't seem to be able to delete them.

For example, this code doesn't work:

import curses
def fill(window, ch):
    y, x = window.getmaxyx()
    s = ch * (x - 1)
    for line in range(y):
        window.addstr(line, 0, s)

def main(stdscr):
    fill(stdscr, 'M')
    stdscr.refresh()
    stdscr.getch()

    subwin = stdscr.subwin(1, 28, 20, 13)
    fill(subwin, 'J')
    subwin.refresh()
    subwin.getch()

    del subwin
    stdscr.touchwin()
    stdscr.refresh()
    stdscr.getch()

curses.wrapper(main)

When you run this code, the screen fills with 'M', then when you hit a key, a subwindow is created and filled with 'J'. Finally, when you press a key again, the code deletes the subwindow and completely redraws the screen. However, those Js are still there.

After some experimentation, I've found that calling the clear() method of stdscr will make the subwindow go, but I would like to restore the background as it was, without blanking it and rewriting. Does anyone know a way in which this could be done?

like image 333
MageJohn Avatar asked Jan 28 '13 21:01

MageJohn


People also ask

What is the curses module in Python?

What is curses? ¶ The curses library supplies a terminal-independent screen-painting and keyboard-handling facility for text-based terminals; such terminals include VT100s, the Linux console, and the simulated terminal provided by various programs.

Does Python curses work on Windows?

For a tutorial on how to use curses, check out Curses Programming in Python. The curses package is part of the Python standard library and is useful for creating text-based user interfaces and generally controlling the screen and keyboard input. The big problem is that it doesn't work out-of-the-box on Windows.

Does curses come with Python?

The curses package comes with the Python standard library. In Linux and Mac, the curses dependencies should already be installed so there is no extra steps needed. On Windows, you need to install one special Python package, windows-curses available on PyPI to add support.


1 Answers

Is there a good reason why you're using a subwindow? If you create a new top-level window then the code works correctly - simply change stdscr.subwin to curses.newwin and it works as you'd expect.

I'm not a curses expert, but I believe a subwindow shares the character buffer with its parent such that changes to either one will also affect the other. So, if you're looking to sub-divide a window into logical areas (perhaps a menu bar, main area and status bar) then subwindows are useful. If, however, you're looking for something more like a dialog box or pop-up menu then a whole new window (with its own separate buffer) is what you're after.

I can't find any definitive reference for ncurses which agrees or disagrees with me, but man page for AIX seems to corroborate it:

Recall that the subwindow shares its parent's window buffer. Changes made to the shared window buffer in the area covered by a subwindow, through either the parent window or any of its subwindows, affects all windows sharing the window buffer.

Of course, this isn't definitive for ncurses, but I can't find anything to the contrary and it certainly seems to explain the behaviour observed. I also did a crude experiment where, immediately after the subwin.getch() line in your example, I added this line:

raise Exception(stdscr.instr(20, 15, 3))

In your example, I get JJJ as the content of the actual main window. If I change to use curses.newwin() to create the window instead of stdscr.subwin() I get the expected MMM.

I don't know how many specific Python curses resources there are, but most of the standard tutorials and documents about ncurses are quite useful for this sort of level. Back when I had to do some work in it, this document was quite useful. If you scroll down to the "An Example" section, you'll see that the menu pop-ups are not subwindows - he alludes to this with the following slightly vague explanation:

We don't want this new window to overwrite previously written characters on the background. They should stay there after the menu closes. This is why the menu window can't be created as a subwindow of stdscr.

Also, I remember that using both stdscr and your own windows can cause issues - the "official" ncurses introduction has some warnings about this sort of thing. It also suggests avoiding overlapping windows entirely, as they're apparently error-prone, but I don't recall having any issues with them for short-term transient modal dialogs (which is the only use to which I put them). Of course, just because my simple use-case didn't expose any issues doesn't mean there aren't any. In something as complicated as ncurses, however, I can see the wisdom in keeping things as simple as you can.

I hope that's some help. As I said, I'm by no means a curses expert, but hopefully this gets you a few steps further along.

like image 168
Cartroo Avatar answered Nov 14 '22 23:11

Cartroo