Python中的控制台菜单生成器

Qua*_*tum 3 python console eval menu generator

正如标题所说,我正在用Python编写控制台菜单生成器.我有2个课程,菜单和项目.但是我遇到了麻烦.这是代码:

class Menu:
    def AddItem(self,item):
        class Item:
            def __init__(self,text,ToDoNext):
                self.text=text
                ??????????????
        self.item.append(Item())
    def Show():
        for i in range(len(self.item)):
            print(str(i+1)+") "+str(self.item[i])+"\n")
        print("0) Back\n")
        option=int(input())
        self.item[option].????????????
Run Code Online (Sandbox Code Playgroud)

这段代码基本上是下一步:

Main=Menu()
Menu.AddItem("Open file",ToDo1)
Menu.AddItem("Save file",ToDo2)
Menu.Show()

'''1) Open file
   2) Save file
   0) Back
   _
'''
Run Code Online (Sandbox Code Playgroud)

如果我写1并按Enter键应该执行代码部分ToDo1,例如.我认为的解决方案是下一个:

def ToDo1():
    print("Hello, world!")
Menu.AddItem("Say Hello","ToDo1()")
Run Code Online (Sandbox Code Playgroud)

并使用eval()内部的功能Show().

但我不确定这不是正确的方法.

我希望你能告诉我一个更好的方法,如果你曾经做过类似的事情(控制台菜单生成器)来共享代码并看到另一种方法.

小智 6

我绝对建议创建一个类Item,即使你只有textfunction属性!谁知道你以后需要什么样的复杂逻辑.考虑到这一点,创建菜单可能看起来像这样:

main = Menu()
main.AddItem(Item("Open", openFile))
main.AddItem(Item("Close", closeFile))
Run Code Online (Sandbox Code Playgroud)

此外,在您的textfunction属性之上,您应该parentItem该类添加属性.parent只需指向我们项目的父菜单:

main = Menu()

# automatically calls main.AddItem(item1)
open = Item("Open", openFile, main)

# automatically sets parent to main
main.Add(Item("Close", closeFile))
Run Code Online (Sandbox Code Playgroud)

既然我们知道如何正确Menu并且Item应该工作,我们就可以开始编写类了.


菜单

这应该不是太难,我们需要的是add_item(),remove_item()draw()方法的列表和items.绘制菜单名称也很好,所以让我们添加name属性.

class Menu:
    def __init__(self, name, items=None):
        self.name = name
        self.items = items or []

    def add_item(self, item):
        self.items.append(item)
        if item.parent != self:
            item.parent = self

    def remove_item(self, item):
        self.items.remove(item)
        if item.parent == self:
            item.parent = None

    def draw(self):
        print(self.label)
        for item in self.items:
            item.draw()
Run Code Online (Sandbox Code Playgroud)

显然,我们可以为菜单编写更多的方法和属性,但这包括所有必要的方法.


项目

项目类应该更容易,它几乎不需要任何方法.项目显然需要a name和a function(当项目被激活时将运行函数),最重要的是它具有前面提到的parent属性.我们可能应该创建一个setter parent,它会自动将项目移动到另一个菜单下,但如果你想这样做,我会留给你.另外,不要忘记draw()项目的方法,我们必须能够以他们想要绘制的方式绘制我们的项目,而不是我们Menu想要绘制它们的方式.

class Item:
    def __init__(self, name, function, parent=None):
        self.name = name
        self.function = function
        self.parent = parent
        if parent:
            parent.add_item(self) # use add_item instead of append, since who
                                  # knows what kind of complex code you'll have
                                  # in add_item() later on.

    def draw(self):
        # might be more complex later, better use a method.
        print("    " + self.name)
Run Code Online (Sandbox Code Playgroud)

最后的想法

我们现在已经完成了菜单,它可以工作,您应该可以将它用作基本菜单.但是,高级控制台菜单只能调用一个类MenuItem.每个项目的父项都是另一项MenuItem(每个项目,但MenuItem当然是根目录),菜单在绘制时看起来像这样:

[-] Root
    [+] Submenu of Root
    [-] An other submenu of Root
          This menu runs functions, others open/close
         <This menu has focus on it>
          Select this menu by pressing mousedown
    [+] A third submenu of Root
Run Code Online (Sandbox Code Playgroud)

不给出function参数的地方会创建items列表并允许用户关闭/打开menuitem.如果function给定,它将正常工作,并且仅在选中时执行该功能.为了更进一步,我们将分开MenuItem两个子类:ActionMenuContainerMenu.但请记住,这有点难以编码,而不适合初学者.你可能想坚持我经历的第一个版本.