我需要你帮助理解基于python程序的新菜单中的错误。
我使用curses库创建了一个基于菜单的python。通过getch()
获取用户输入时,通过接受所有键(包括特殊键作为输入),该程序可以正常使用主菜单选项,但是通过子菜单列表,它无法接受特殊键作为输入。
# Increment or Decrement
elif c == curses.KEY_DOWN: # down arrow
if self.option < len(self.submenu):
self.option += 1
else: self.option = 0
elif c == curses.KEY_UP: # up arrow
if self.option > 0:
self.option -= 1
else: self.option = len(self.submenu)
所以上面是条件我用来选择选项但是当我使用向上/向下箭头键时没有输入到curses
我在下面分享我的完整代码
import curses, os, traceback, json
file1 = json.loads(open('/etc/ansible/org/json/tag_definition.json').read())
submenu = list(file1.keys())
cfg_dict = {'InstanceName': 'NONE',
'Environment': 'NONE',
'InstanceType':'t2.micro',
'SystemOwner':'1',
'LifeCycle':'NONE',
'DeptName':'NONE',
'Org':'NONE'}
class CursedMenu(object):
'''A class which abstracts the horrors of building a curses-based menu system'''
def __init__(self):
'''Initialization'''
self.screen = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
self.screen.keypad(1)
# Highlighted and Normal line definitions
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)
self.highlighted = curses.color_pair(1)
self.normal = curses.A_NORMAL
def show(self, options, title="Title", subtitle="Subtitle"):
'''Draws a menu with the given parameters'''
self.set_options(options)
self.title = title.upper()
self.subtitle = subtitle.upper()
self.selected = 0
self.draw_menu()
def set_options(self, options):
'''Validates that the last option is "Exit"'''
if options[-1] is not 'Exit':
options.append('Exit')
self.options = options
def set_submenu(self, submenu):
'''Validates that the last option is "Exit"'''
if submenu[-1] is not 'Exit':
submenu.append('Exit')
self.submenu = submenu
def draw_dict(self):
self.screen.addstr(8, 35, " "*43, curses.A_BOLD)
self.screen.addstr(10, 35," "*43, curses.A_BOLD)
self.screen.addstr(12, 35," "*43, curses.A_BOLD)
self.screen.addstr(14, 35," "*43, curses.A_BOLD)
self.screen.addstr(16, 35," "*43, curses.A_BOLD)
self.screen.addstr(18, 35," "*43, curses.A_BOLD)
self.screen.addstr(20, 35," "*43, curses.A_BOLD)
self.screen.addstr(8, 35, cfg_dict['InstanceName'], curses.A_STANDOUT)
self.screen.addstr(10, 35,cfg_dict['Environment'], curses.A_STANDOUT)
self.screen.addstr(12, 35,cfg_dict['InstanceType'], curses.A_STANDOUT)
self.screen.addstr(14, 35,cfg_dict['SystemOwner'], curses.A_STANDOUT)
self.screen.addstr(16, 35,cfg_dict['LifeCycle'], curses.A_STANDOUT)
self.screen.addstr(18, 35,cfg_dict['DeptName'], curses.A_STANDOUT)
self.screen.addstr(20, 35,cfg_dict['Org'], curses.A_STANDOUT)
self.screen.refresh()
def draw_menu(self):
'''Actually draws the menu and handles branching'''
request = ""
try:
while request is not "Exit":
self.draw()
request = self.get_user_input()
self.handle_request(request)
self.__exit__()
# Also calls __exit__, but adds traceback after
except Exception as exception:
self.__exit__()
traceback.print_exc()
def draw(self):
'''Draw the menu and lines'''
#self.screen.border(0)
self.screen.subwin(40, 80, 0, 0).box()
self.screen.addstr(2,30, self.title, curses.A_STANDOUT|curses.A_BOLD) # Title for this menu
self.screen.hline(3, 1, curses.ACS_HLINE, 78)
self.screen.addstr(4,2, self.subtitle, curses.A_BOLD) #Subtitle for this menu
# Display all the menu items, showing the 'pos' item highlighted
left = 2
for index in range(len(self.options)):
menu_name = len(self.options[index])
textstyle = self.normal
if index == self.selected:
textstyle = self.highlighted
self.screen.addstr(5, left, "%d.%s" % (index+1, self.options[index]), textstyle)
left = left + menu_name + 3
self.screen.addstr(8, 4, " Instance Name:", curses.A_BOLD)
self.screen.addstr(10, 4," Environment:", curses.A_BOLD)
self.screen.addstr(12, 4," Instance Type:", curses.A_BOLD)
self.screen.addstr(14, 4," SystemOwner:", curses.A_BOLD)
self.screen.addstr(16, 4," LifeCycle:", curses.A_BOLD)
self.screen.addstr(18, 4," Department Name:", curses.A_BOLD)
self.screen.addstr(20, 4," Org:", curses.A_BOLD)
self.draw_dict()
self.screen.refresh()
def get_user_input(self):
'''Gets the user's input and acts appropriately'''
user_in = self.screen.getch() # Gets user input
'''Enter and Exit Keys are special cases'''
if user_in == 10:
return self.options[self.selected]
if user_in == 27:
return self.options[-1]
if user_in == (curses.KEY_END, ord('!')):
return self.options[-1]
# This is a number; check to see if we can set it
if user_in >= ord('1') and user_in <= ord(str(min(9,len(self.options)+1))):
self.selected = user_in - ord('0') - 1 # convert keypress back to a number, then subtract 1 to get index
return
# Increment or Decrement
if user_in == curses.KEY_LEFT: # left arrow
self.selected -=1
if user_in == curses.KEY_RIGHT: # right arrow
self.selected +=1
self.selected = self.selected % len(self.options)
return
def handle_request(self, request):
'''This is where you do things with the request'''
if request is "Org":
self.org_func()
if request is None: return
def org_func(self):
'''Actually draws the submenu and handles branching'''
c = None
self.option = 0
self.set_submenu(submenu)
height = len(self.submenu)
while c != 10:
self.s = curses.newwin(height+2, 20, 6, 14)
self.s.box()
for index in range(len(self.submenu)):
textstyle = self.normal
if index == self.option:
textstyle = self.highlighted
self.s.addstr(index+1,1, "%d-%s" % (index+1, self.submenu[index]), textstyle)
self.s.refresh()
c = self.s.getch() # Gets user input
if c == ord('k'):
d = self.submenu[self.option]
cfg_dict['Org'] = file1[d]['Org']
# This is a number; check to see if we can set it
if c >= ord('1') and c <= ord(str(len(self.submenu)+1)):
self.option = c - ord('0') - 1 # convert keypress back to a number, then subtract 1 to get index
# Increment or Decrement
elif c == curses.KEY_DOWN: # down arrow
if self.option < len(self.submenu):
self.option += 1
else: self.option = 0
elif c == curses.KEY_UP: # up arrow
if self.option > 0:
self.option -= 1
else: self.option = len(self.submenu)
return self.option
def __exit__(self):
curses.endwin()
os.system('clear')
'''demo'''
cm = CursedMenu()
cm.show(['Instance-ID','Org','Tag'], title='Instance Launch', subtitle='Options')
如果我使用字母和数字作为输入但不使用特殊键,它的效果非常好。我使用了下面的代码并且它正在工作
elif c == ord('k'): # down arrow
if self.option < len(self.submenu):
self.option += 1
else: self.option = 0
elif c == ord('i'): # up arrow
if self.option > 0:
self.option -= 1
else: self.option = len(self.submenu)
请帮助理解为什么代码不接受特殊密钥。
下面是我使用的输入json
{
"Dept1": {
"Instance Name": "instance1",
"Environment": "environment1",
"SystemOwner": "Owner1",
"LifeCycle": "Lcy1",
"DeptName": "Check1",
"Org": "CSO"
}
}
答案 0 :(得分:2)
当你做了
self.s = curses.newwin(height+2, 20, 6, 14)
您省略了新窗口的设置属性,例如
self.s.keypad(1)