I'm trying to get into Curses using Python and I'm fairly new to both subjects. I'm trying to make a scrollable menu object, and so far it looks decent but the issue I'm having is when scrolling through some test data, the window border disappears. I've tried window.clear() and window.refresh() throughout several points in the code but nothing I do makes the border persistent.
#!/usr/bin/python
import curses
import curses.panel
class CursesMenu():
pos = 0
c = None
menuItems = None
selection = None
dimensions = None
MAX_DISPLAYED = 5
displayList = list(range(MAX_DISPLAYED))
subwin_key_up = None
subwin_key_down = None
def __init__(self, menuItems=None):
self.menuItems = menuItems
curses.wrapper(self.main_menu, menuItems)
def scrollDisplayUp(self): #shift each element of displayList down one
for i in range(len(self.displayList)):
self.displayList[i] -= 1
def scrollDisplayDown(self): #shift each element of displayList up one
for i in range(len(self.displayList)):
self.displayList[i] += 1
def posUp(self, win): # Lower pos = higher placement
if self.pos == 0: #loop back around
self.pos = len(self.menuItems) - 1
self.displayList = list(range(len(self.menuItems) - self.MAX_DISPLAYED, len(self.menuItems)))
win.clear()
else:
self.pos -= 1
def posDown(self, win): # Higher pos = lower placement
if self.pos >= len(self.menuItems) - 1: #loop back around
self.pos = 0
self.displayList = list(range(self.MAX_DISPLAYED))
win.clear()
else:
self.pos += 1
def main_menu(self, win, menuItems=None):
self.dimensions = win.getmaxyx()
curses.curs_set(0) #invisible cursor
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
highlighted = curses.color_pair(1)
normal = curses.A_NORMAL
sub = win.subwin(self.MAX_DISPLAYED + 2, 20, 1, 1)
sub.immedok(True) #jet fuel can't melt steel beams
sub.box()
while self.c != ord('\n'): #run until 'enter' gets pressed
sub.box()
self.dimensions = win.getmaxyx()
if self.c == curses.KEY_UP:
self.posUp(sub)
if self.pos <= self.displayList[0] - 1:
self.scrollDisplayUp()
sub.clear()
sub.refresh()
if self.c == curses.KEY_DOWN:
self.posDown(sub)
if self.pos >= self.displayList[-1] + 1:
self.scrollDisplayDown()
sub.clear()
sub.refresh()
for i, j in zip(self.displayList, range(self.MAX_DISPLAYED)):
if i != self.pos:
sub.addstr(j+1, 1, menuItems[i], normal)
else:
sub.addstr(j+1, 1, menuItems[i], highlighted)
self.c = win.getch()
self.selection = menuItems[self.pos]
Here's a tiny script I'm using to test it:
#!/usr/bin/python
import cursesmenu
menulist=['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo', 'Foxtrot', 'Golf', 'Hotel', \
'India', 'Juliett', 'Kilo', 'Lima', 'Mike', 'November', 'Oscar', 'Papa', 'Quebec', \
'Romeo', 'Sierra', 'Tango', 'Uniform', 'Victor', 'Whiskey', 'Xray', 'Yankee', 'Zulu']
m = cursesmenu.CursesMenu(menulist)
print m.selection
print m.dimensions
Thanks Anand, that solved the disappearing border, but then I found the stale text was sticking around. I fixed the issue by putting back the sub.clear() with sub.border(0) and sub.refresh() after.