Python ncurses: doesn't display screen until first key press though update first

The code below allows you to navigate a small grid on the screen using the arrow keys, placing ".". where you studied or were near. Despite the fact that I have an update to the first getch (to get the key stroke), the screen does not display anything until you leave your starting position. Should you update addstr immediately after that, after which getch waits after that? I even tried adding stdscr.refresh (), but that didn't help either. How to make the screen refresh immediately before waiting for the first keystroke?

import curses def start(stdscr): curses.curs_set(0) movement = curses.newpad(10, 10) cur_x, cur_y = 5, 5 while True: movement.addstr(cur_y, cur_x, '@') for (x_off, y_off) in [(-1,0),(1,0),(0,-1),(0,1)]: movement.addstr(cur_y + y_off, cur_x + x_off, '.') movement.refresh(1, 1, 0, 0, 7, 7) #Nothing is displayed until after the first key-stroke key_stroke = stdscr.getch() move_attempt = False if 0 < key_stroke < 256: key_stroke = chr(key_stroke) elif key_stroke == curses.KEY_UP and cur_y > 1: cur_y -= 1 elif key_stroke == curses.KEY_DOWN and cur_y < 8: cur_y += 1 elif key_stroke == curses.KEY_LEFT and cur_x > 1: cur_x -= 1 elif key_stroke == curses.KEY_RIGHT and cur_x < 8: cur_x += 1 else: pass if __name__ == '__main__': curses.wrapper(start) 
+1
python ncurses python-curses
source share
3 answers

Documents are broken. I used curses that day, but libncurses is new to me.

My first hint came from ncurses (3) :

The ncurses library allows you to manipulate data structures called windows, which can be thought of as two-dimensional character arrays representing all or part of a CRT screen. A default window is supplied, called stdscr, which is the size of the terminal screen. Others can be created using newwin .... You can also manipulate special windows called shims. These are windows that are not limited by screen size and whose contents do not have to be fully displayed.

But then refresh (3) got decidedly evasive:

Normal wrefresh works by first calling wnoutrefresh, which copies the named window to the virtual screen, and then calling doupdate, which compares the virtual screen to the physical screen and does the actual update .... The phrase "copy the named window to the virtual screen" above is ambiguous. In fact, it happens that all the affected (changed) lines in the window are copied to the virtual screen. This affects programs that use overlapping windows; this means that if two windows overlap, you can update them in any order , and the overlap area will only be changed when it is explicitly changed. [emphasis mine]

which prompted me to try adding

 stdscr.refresh() 

after your pad.refresh() , which worked. And then I moved it further to start() to see if it was really necessary for each modification of the pad. I moved all this to the first point where there is stdscr for working with the crop:

 def start(stdscr): stdscr.refresh() curses.curs_set(0) … 

which will bring in voodoo programming, but I won’t look at the insides of a 20 year old library to deal with glass ttys to try to figure it out.

+4
source share

Add stdscr.refresh() earlier than movement.refresh() to solve the problem.

By adding time.sleep(1) after the update statement, it writes to the screen, but then it disappears when stdscr.getch() called, but only for the first time. This is probably due to some delay in stdscr initialization.

Calling stdscr.refresh() after movement.refresh() has the same effect: the very first time through the stdscr.refresh() loop the screen is cleared, but not at subsequent times through the loop. stdscr.refresh() calling stdscr.refresh() at the beginning of the program, he gets this strange first time update.

+2
source share

When using a pad for some reason - I don't know why - you should call curses.doupdate after calling refresh .

0
source share

All Articles