2013-02-26 44 views
3

正如标题所说,我正在用Python编写一个控制台菜单生成器。我有2个课程,菜单和项目。但我陷入困境。下面是代码:Python中的控制台菜单生成器

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].???????????? 

此代码基本上做到了下:

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

'''1) Open file 
    2) Save file 
    0) Back 
    _ 
''' 

如果我写1,然后按回车应该做的代码ToDo1的部分,例如。 ,我认为该解决方案是nextone:

def ToDo1(): 
    print("Hello, world!") 
Menu.AddItem("Say Hello","ToDo1()") 

,并使用Show()内的eval()功能。

但我不敢肯定这不是做这件事的正确方法。

我想让你给我一个更好的方法,如果你曾经做过类似的事情(控制台菜单生成器)来分享代码,并看到另一种方式做同样的事情。

回答

0

函数可以在Python中自由传递。如果你说AddItem("Say Hello", ToDo1),你传递值ToDo1,这是一个函数对象。然后,您可以将其存储在self.function中,稍后用fn = self.item[option].function进行钓鱼,然后用fn()与之联系。当你意识到像do_stuff()这样的常规函数​​调用实际上是两件事情时,它更清晰:首先从变量do_stuff(通常是永不改变的全局变量)获取函数对象,然后调用该函数对象。

0

这里是一个工作示例

通常类菜单部分将是所谓的“MYMENU”和进口与命令from myMenu import myMenu

项另一个文件是字典的阵列。每个列表项有两个条目,“文本”和“功能”

为数组为零

import sys 
class myMenu: 
    items=[] 

    def AddItem(self,text,function): 
     self.items.append({'text': text, 'func':function}) 

    def Show(self): 
     c=1 
     for l in self.items: 
      print c, l['text'],"\n" 
      c = c +1 

    def Do(self,n): 
     self.items[n]['func']() 

def clist(): 
    print "cheeses are wensleydale and cheddar\n" 

def bye(): 
    print "bye" 
    sys.exit(0) 

if __name__ == "__main__": 
    m=myMenu() 
    m.AddItem("cheese",clist) 
    m.AddItem("quit",bye) 

while(True): 
    m.Show() 
    n=input("choice>") 
    m.Do(n-1) 

开始如果你想有菜单项的输入被称为N-1的字典一类,而不是一本字典,然后立即声明类类的MyMenu后,所以像这样(未测试)

class myMenu: 
    items=[] 
    class Item: 
     func=None 
     text="default" 

     def __init__(self,t,f): 
      self.text=t 
      self.func=f 

    def AddItem(self,text,function): 
     self.items.append(Item(text,function)) 
6

我绝对建议创建一个类Item,即使你只有textfunction属性!谁知道你以后需要什么样的复杂逻辑。 考虑到这一点,造就了菜单可能会是这个样子:

main = Menu() 
main.AddItem(Item("Open", openFile)) 
main.AddItem(Item("Close", closeFile)) 

此外,您textfunction属性之上,你应该添加parent属性到Item类。 parent只需在我们的项目的父菜单指出:

main = Menu() 

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

# automatically sets parent to main 
main.Add(Item("Close", closeFile)) 

现在我们知道如何适当MenuItem应该工作,我们就可以开始编写类。


菜单

这应该不是太难,我们需要的是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() 

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


项目

项目类应该是更容易,它几乎不需要任何方法都没有。 该项目显然需要一个name和一个function(函数将在物件被激活时运行),最重要的是它具有前面提到的parent属性。 我们可能应该为parent创建一个setter,它会自动将该项目移动到其他菜单下,但如果您想要这样做,我会为您保留该项目。 也不要忘记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) 

最后的想法

现在,我们已经完成了我们的菜单,它的工作原理,你应该能够使用它作为一个基本的菜单。 但是,卓越的控制台菜单将只有一个名为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 

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

+0

有人真的花了一些时间在菜单上工作?这给了我很多新的信息,完全得到了我的赞赏! – 2013-02-26 10:02:59