Ich persönlich würde eine
DSL erfinden und benutzen, um derartige Menüs zu definieren. Zum Beispiel so:
Code: Alles auswählen
menu_bar(
menu("Programm",
item("&Informationen", help_text="Informationen über das Programm", action=self.onAbout),
item("&Beenden", help_text="...", action=self.onExit),
),
...
)
Letztlich wird das die selbe Struktur mit Tupel und Listen erzeugen, doch das ist um eine Größenordnung leichter zu lesen und zu verstehen, finde ich.
Es könnte auch interessant sein, folgenden Ansatz mal auszuprobieren:
Code: Alles auswählen
@menu_item("About", in_menu="Programm", help_text="...")
def onAbout():
...
@menu_item("Beenden", in_menu="Programm", help_text="...")
def onExit():
....
Vorteil wäre, dass man sich so sein Menü relativ dynamisch zusammenbauen kann. Nachteil wäre, dass das Menu relativ dynamisch zusammengebaut ist und z.B. die Reihenfolge der Menüeintrage schwer zu definieren ist.
Da es mir allgemein besser erscheint, ein Command-Pattern zu benutzen und nicht einfach nur Funktionen, wäre eine Kombination beider Ansätze denkbar:
Code: Alles auswählen
class AboutCmd(Command):
label = "About"
help_text = "..."
def execute(): ...
class ExitCmd(Command):
label = "Beenden"
def execute(): ...
menu_bar(
menu("Programm", AboutCmd, ExitCmd, ...),
)
Das würde (mit weniger Aufwand) dem Weg entsprechen, wie man das z.B. in der Eclipse-Plattform sieht. Es gibt dann verschiedene Arten von Kommandos: Welche, die man rückgängig machen (UndoableCommand) kann und welche, die die Undo-Liste löschen usw. Kommandos kann man dann sowohl in der zentralen Menüleiste, also auch in Form von Schaltflächen in der Funktionsleiste als auch als einzelne Schaltflächen vorfinden. Kommando-Exemplare könnten zudem wissen, ob sie gerade erlaubt sind (enablement state), dann können diese aber wiederum keinen Zustand für das Undo speichern, weil jetzt Kommando-Exemplare und nicht mehr Kommando-Klassen über die Menüleiste referenziert werden.
Egal, was ich sagen wollte ist: Nimm nicht einfach nur Listen, mach es lesbar und abstrahiere dabei. Nutze die Möglichkeiten der Metaprogrammierung.
Stefan