3

正如标题所说,我正在用 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].????????????

这段代码基本上做了下一个:

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

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

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

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

eval()Show().

但我不太确定这不是正确的方法。

我希望您向我展示一种更好的方法,如果您曾经做过类似的事情(控制台菜单生成器)来共享代码并查看另一种方法。

4

4 回答 4

7

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

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

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

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()itemsname

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()

显然,我们可以为菜单编写更多方法和属性,但这包括所有基本方法。


物品

项目类应该更容易,它几乎不需要任何方法。Item 显然需要 aname和 a function(当 item 被激活时将运行函数),除此之外它还具有前面提到的parent属性。我们可能应该创建一个 setter parent,它会自动将项目移动到另一个菜单下,但如果你想这样做,我会留给你。也不要忘记draw()item 的 - 方法,我们必须能够以他们想要的方式绘制我们的项目,而不是我们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(每个,但当然是 rootMenuItem的),并且菜单在绘制时看起来像这样:

[-] 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。但请记住,这有点难以编码,不适合初学者。你可能想坚持我经历的第一个版本。

于 2013-02-26T09:39:31.573 回答
0

函数可以在 Python 中自由传递。如果您说AddItem("Say Hello", ToDo1),则传递 value ToDo1,它是一个函数对象。然后您可以将其存储在 中self.function,稍后使用 钓鱼fn = self.item[option].function,然后使用 调用它fn()。当您意识到像这样的常规函数​​调用do_stuff()实际上是两件事时,一切就更清楚了:首先从变量中获取函数对象do_stuff(通常是一个从未修改过的全局变量),然后调用这个函数对象。

于 2013-02-26T09:08:24.527 回答
0

这是一个工作示例

通常类菜单部分会在另一个名为“myMenu”的文件中,并使用命令导入from myMenu import myMenu

items 是一个字典数组。每个列表项都有一个包含两个条目的字典,“text”和“func”

输入称为 n-1,因为数组从零开始

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)

如果您想将菜单项作为类而不是字典,则在 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))
于 2013-02-26T09:10:33.410 回答
0

给未来的读者!使用 .python 控制台菜单很容易console-menu

pip install console-menu

现在,让我们实现我们的菜单

from consolemenu import *
from consolemenu.items import *

# Create the menu
menu = ConsoleMenu("Title", "Subtitle")

# Create some items

# MenuItem is the base class for all items, it doesn't do anything when selected
menu_item = MenuItem("Menu Item")

# A FunctionItem runs a Python function when selected
function_item = FunctionItem(
    "Call a Python function", input, ["Enter an input"]
)

# A CommandItem runs a console command
command_item = CommandItem("Run a console command", "touch hello.txt")

# A SelectionMenu constructs a menu from a list of strings
selection_menu = SelectionMenu(["item1", "item2", "item3"])

# A SubmenuItem lets you add a menu (the selection_menu above, for example)
# as a submenu of another menu
submenu_item = SubmenuItem("Submenu item", selection_menu, menu)

# Once we're done creating them, we just add the items to the menu
menu.append_item(menu_item)
menu.append_item(function_item)
menu.append_item(command_item)
menu.append_item(submenu_item)
menu.show()

你会得到这样的菜单 在此处输入图像描述

于 2021-12-04T05:12:23.893 回答