I would like to move a curses pad across the screen, but I can't figure out a way to automatically erase the pad from the previous position in the screen without erasing the contents of the pad. I don't want to have to redraw the pad every time I move it. Here's my test program:
import curses
import time
def main(stdscr):
pad = curses.newpad(10, 10)
ch = ord('A')
pad.addch(4, 4, ch)
for y in range(0, 10):
for x in range(0, 10):
print("adding pad at {y},{x}")
try:
pad.insch(y, x, ch)
except:
pass
if x % 9 == 0:
ch += 1
pad.refresh(0, 0, 0, 0, 10, 10)
time.sleep(2)
pad.refresh(0, 0, 1, 1, 11, 11)
time.sleep(2)
pad.refresh(0, 0, 2, 2, 12, 12)
time.sleep(2)
curses.wrapper(main)
At the end of this script, the window looks like:
AAAAAAAAAA
BAAAAAAAAAA
CBAAAAAAAAAA
DCBBBBBBBBBB
EDCCCCCCCCCC
FEDDDDDDDDDD
GFEEEEEEEEEE
HGFFFFFFFFFF
IHGGGGGGGGGG
JIHHHHHHHHHH
JIIIIIIIIII
JJJJJJJJJJ
The first two lines and the first two characters of each line are leftover from previous pad displays. I want these erased.
I can create a different pad with the same dimensions and use it to erase the block from the screen:
def main(stdscr):
pad = curses.newpad(10, 10)
erasepad = curses.newpad(10, 10)
ch = ord('A')
pad.addch(4, 4, ch)
for y in range(0, 10):
for x in range(0, 10):
print("adding pad at {y},{x}")
try:
pad.insch(y, x, ch)
except:
pass
if x % 9 == 0:
ch += 1
pad.refresh(0, 0, 0, 0, 10, 10)
time.sleep(2)
erasepad.refresh(0, 0, 0, 0, 10, 10)
pad.refresh(0, 0, 1, 1, 11, 11)
time.sleep(2)
erasepad.refresh(0, 0, 1, 1, 11, 11)
pad.refresh(0, 0, 2, 2, 12, 12)
time.sleep(2)
That's workable for my application, but is there a more efficient way? This requires me to create two pads for every animation block, and to completely erase every pad every time.
That's roughly the case. The sample code is inefficient however, doing extra repainting. Take a look at noutrefresh
and doupdate
(to replace those refresh calls), and replace the time.sleep
with napms
(again, to improve performance).