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
   _
'''

ToDo11を書き込み、Enterを押すと、たとえばコードの部分を実行する必要があります。私が思った解決策は次のものだと思った:

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

eval()内で関数を使用しますShow()

しかし、これが正しい方法ではないかどうかはわかりません。

より良い方法を教えていただきたいのですが、そのようなこと (コンソール メニュー ジェネレーター) を行ったことがある場合は、コードを共有して、同じことを行う別の方法を確認してください。

4

4 に答える 4

7

属性Itemしかない場合でも、クラスを作成することを強くお勧めしtextます。function後で必要になる複雑なロジックの種類を誰が知っていますか。これを念頭に置いて、メニューの作成はおそらく次のようになります。

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

また、属性に加えて、クラスtextに属性をfunction追加する必要があります。アイテムの親メニューをポイントするだけです。parentItemparent

main = Menu()

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

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

Menu適切で機能する方法がわかったのでItem、クラスのコーディングを開始できます。


メニュー

これはそれほど難しいことではありません。必要なのは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()

もちろん、メニューにはもっと多くのメソッドと属性をコーディングできますが、これにはすべての重要なメソッドが含まれています。


アイテム

アイテムクラスはさらに簡単なはずです。メソッドはほとんど必要ありません。アイテムには明らかにanameとaが必要functionです(アイテムがアクティブ化されると関数が実行されます)。さらに、前述のparent属性があります。おそらく、他のメニューの下にアイテムを自動的に移動するセッターを作成する必要がありparentますが、必要に応じてそれを残しておきます。また、アイテムの-methodも忘れないでください。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)

最終的な考え

これでメニューが完成しました。これで機能し、基本メニューとして使用できるようになります。ただし、優れたコンソールメニューには、と呼ばれるクラスが1つだけあります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、2つのサブクラスを分離します:ActionMenuContainerMenu。ただし、これはコーディングがやや難しく、初心者向けではないことに注意してください。あなたは私が経験した最初のバージョンに固執したいかもしれません。

于 2013-02-26T09:39:31.573 に答える
0

これが実際の例です

通常、クラス メニュー パーツは「myMenu」という別のファイルにあり、コマンドでインポートされます。from myMenu import myMenu

items は辞書の配列です。各リスト項目には、「text」と「func」の 2 つのエントリを持つ辞書があります。

配列はゼロから始まるため、入力は 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 では、関数を自由に渡すことができます。という場合は、関数オブジェクトであるAddItem("Say Hello", ToDo1)値を渡します。ToDo1それを に保存しself.function、後で で釣り上げ、 でfn = self.item[option].function呼び出すことができfn()ます。のような通常の関数呼び出しdo_stuff()が実際には 2 つのことであることに気付くと、より明確になります。最初に変数do_stuff(通常は変更されないグローバル変数) から関数オブジェクトを取得し、次にこの関数オブジェクトを呼び出します。

于 2013-02-26T09:08:24.527 に答える