Python curses不接受curses.KEY_UP作为输入

时间:2016-08-17 17:26:04

标签: python menuitem curses

我需要你帮助理解基于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"

   }
}

1 个答案:

答案 0 :(得分:2)

当你做了

self.s = curses.newwin(height+2, 20, 6, 14)

您省略了新窗口的设置属性,例如

self.s.keypad(1)