Bitte Ratschläge für Console-MenuFührung...

SteHa

Mitglied
Hallo Leut!
Vorneweg: Ich bin 59Jahre alt und wünschte mir ein paar Vorschläge ihrerseits. (also keine Hausaufgaben, nur reinstes Hobby)

Folgender Code ist vorgeschlagen vom Copilot, nach der Aufforderung von mir (eine Consolen-Menu Führung), meinen Code in irgendein Entwurfsmuster einzubetten.

Das Resultat, das Command Pattern.
Ich kann den Code nachvollziehen. Abgesehen davon, dass das mit Kanonen auf Spatzen schießen ist, für mein kleines Programm.
Also bitte, bitte!
Gerne auch abstract...

Java:
import java.util.Scanner;
import java.util.HashMap;
import java.util.Map;

// Hauptklasse, die das Menü steuert
public class MainMenu {
    private Scanner scanner = new Scanner(System.in);
    private Map<Integer, Command> commands = new HashMap<>();

    public MainMenu() {
        commands.put(1, new SubMenu1Command());
        commands.put(2, new SubMenu2Command());
        commands.put(3, new SubMenu3Command());
        commands.put(4, new ExitCommand());
    }

    public void display() {
        int mainChoice;
        do {
            System.out.println("Hauptmenü:");
            System.out.println("1. Hauptoption 1");
            System.out.println("2. Hauptoption 2");
            System.out.println("3. Hauptoption 3");
            System.out.println("4. Beenden");
            System.out.print("Wähle eine Option: ");
            mainChoice = scanner.nextInt();

            Command command = commands.get(mainChoice);
            if (command != null) {
                command.execute();
            } else {
                System.out.println("Ungültige Auswahl. Bitte versuche es erneut.");
            }
        } while (mainChoice != 4);

        scanner.close();
    }

    public static void main(String[] args) {
        new MainMenu().display();
    }
}

// Command-Interface
interface Command {
    void execute();
}

// Klasse für Untermenü 1
class SubMenu1Command implements Command {
    private Scanner scanner = new Scanner(System.in);

    @Override
    public void execute() {
        int subChoice;
        do {
            System.out.println("Untermenü 1:");
            System.out.println("1. Unteroption 1.1");
            System.out.println("2. Unteroption 1.2");
            System.out.println("3. Zurück zum Hauptmenü");
            System.out.print("Wähle eine Option: ");
            subChoice = scanner.nextInt();

            switch (subChoice) {
                case 1:
                    System.out.println("Unteroption 1.1 ausgewählt");
                    break;
                case 2:
                    System.out.println("Unteroption 1.2 ausgewählt");
                    break;
                case 3:
                    System.out.println("Zurück zum Hauptmenü");
                    break;
                default:
                    System.out.println("Ungültige Auswahl. Bitte versuche es erneut.");
            }
        } while (subChoice != 3);
    }
}

// Klasse für Untermenü 2
class SubMenu2Command implements Command {
    private Scanner scanner = new Scanner(System.in);

    @Override
    public void execute() {
        int subChoice;
        do {
            System.out.println("Untermenü 2:");
            System.out.println("1. Unteroption 2.1");
            System.out.println("2. Unteroption 2.2");
            System.out.println("3. Zurück zum Hauptmenü");
            System.out.print("Wähle eine Option: ");
            subChoice = scanner.nextInt();

            switch (subChoice) {
                case 1:
                    System.out.println("Unteroption 2.1 ausgewählt");
                    break;
                case 2:
                    System.out.println("Unteroption 2.2 ausgewählt");
                    break;
                case 3:
                    System.out.println("Zurück zum Hauptmenü");
                    break;
                default:
                    System.out.println("Ungültige Auswahl. Bitte versuche es erneut.");
            }
        } while (subChoice != 3);
    }
}

// Klasse für Untermenü 3
class SubMenu3Command implements Command {
    private Scanner scanner = new Scanner(System.in);

    @Override
    public void execute() {
        int subChoice;
        do {
            System.out.println("Untermenü 3:");
            System.out.println("1. Unteroption 3.1");
            System.out.println("2. Unteroption 3.2");
            System.out.println("3. Zurück zum Hauptmenü");
            System.out.print("Wähle eine Option: ");
            subChoice = scanner.nextInt();

            switch (subChoice) {
                case 1:
                    System.out.println("Unteroption 3.1 ausgewählt");
                    break;
                case 2:
                    System.out.println("Unteroption 3.2 ausgewählt");
                    break;
                case 3:
                    System.out.println("Zurück zum Hauptmenü");
                    break;
                default:
                    System.out.println("Ungültige Auswahl. Bitte versuche es erneut.");
            }
        } while (subChoice != 3);
    }
}

// Klasse für Beenden
class ExitCommand implements Command {
    @Override
    public void execute() {
        System.out.println("Programm beendet");
    }
}
 

KonradN

Super-Moderator
Mitarbeiter
Also ich sehe da erst einmal kein "mit Kanonen auf Spatzen schießen", denn es ist oft deutlich besser, Code aufzuteilen. Und zwar so, dass Du eigenständige Module / Funktionalitäten / Klassen bekommst, die Du dann einfach testen kannst. Das ist also kein unnötiger Overkill oder so.

Ich würde das sogar noch weiter treiben und ich hätte eine Klasse für ein Menüpunkt. Ein Menüpunkt hat dann z.B.:
  • Eine Beschreibung (das wäre der Text, der angezeigt werden soll)
  • Ein Kürzel (Also ein Zeichen, das eingegeben werden soll zur Auswahl)
  • Eine Liste von Menüpunkten
  • Eine Aktion

Das hätte den Vorteil, dass die Dinge, die zusammen gehören, auch zusammen sind.

Wenn ich mir den Code anschaue, dann fällt mir erst einmal auf, dass es nicht konsequent umgesetzt wurde. So wie das Hauptmenü aufgebaut wurde könntest Du auch die Untermenüs aufbauen. Also auch ein Untermenü hat dann diverse Commands und eben keine switch Anweisung.

Dann wäre das, was ich oben genannt habe, übrigens auch nur noch ein weiterer Schritt: Denn dann würdest Du sehen, dass das Hauptmenü und das Untermenü unter dem Strich den gleichen Aufbau und damit den gleichen Code haben. Und dann könnte man schauen, wie man es vereinheitlichen kann. Und die Ausgabe ist halt unterschiedlich und man hat den direkten Bezug von der Ausgabe eines Menüpunktes hin zu dem Command.

Man kann also tatsächlich über Refactorings schnell das hin bekommen, was ich bereits angedeutet habe.

Aber damit habe ich ja jetzt Deine Sichtweise komplett außen vor gelassen und die war eindeutig:
das mit Kanonen auf Spatzen schießen ist, für mein kleines Programm.

Daher ist dann die Frage, was Du gerne haben möchtest. Eine Möglichkeit, die ich sehe, ist:
Du kannst einfach mit switch Statements arbeiten. In den einzelnen case Anweisungen hast Du dann entweder direkt etwas Code (so es nicht viel ist) oder einen Methodenaufruf.

Das wird dann viel Code mit wenig Funktionalität aber es ist eine unkomplizierte Lösung für Dich.

Aber hier sind ein paar Probleme, die Dir bewusst sein sollten:
  • Änderungen werden sehr aufwändig. Wenn Du eine generelle Änderungen haben willst (z.B. Leerzeile vor "Wähle eine Option." oder statt dessen ein "Bitte treffen Sie eine Auswahl." oder irgend etwas), dann hast viel Aufwand, denn du hast es ja für jedes Menü zu ändern. Wäre es generalisiert, dann wäre nur eine Klasse, die ein Menü anzeigt, zu ändern.
  • Testbarkeit - Bei der Aufteilung bekommst Du Codeteile, die Du für sich testen kannst. Du kannst also die Funktionalität sicher stellen. Vermutlich ist das aber (noch?) kein Thema für Dich.
  • Wiederverwendbarkeit - Wenn du einmal so generelle Klassen geschrieben hast, dann kannst Du diese in allen deinen Projekten verwenden. Immer, wenn Du ein Menü brauchst, hast Du direkt diese Klassen zu Hand und musst deutlich weniger Code schreiben.

Diese Punkte werden oft mit dem Oberbegriff "Clean Code" benannt. Das sind aber Punkte, die vor allem am Anfang eher uninteressant sind und die eher zu Frust führen. Daher ist wichtig: Das ist keinerlei Wertung! Schreibe es wirklich erst einmal so, wie Du es für richtig hältst. Wie es für Dich sinnvoll und einfach scheint. (Das ist auch ein Punkt im Clean Code: Keep it simple, stupid. Du machst also nicht wirklich etwas falsch!) Und hab vor allem Spaß an der Sache und versuch ein Erfolgserlebnis zu bekommen (extrem wichtig für den Spaß!). Wenn es wirklich ein kleines Programm wird, dann ist das ok - wenn es zu groß wird, dann wird die Gefahr von Frust jedoch immer größer!) Dann kannst Du später auch die anderen Dinge ausprobieren und damit herum spielen. Wenn Dich das interessieren würde, dann gerne auch unter Anleitung. Du kannst Dein kleines Programm ja mal als Ganzes zeigen und wir machen konkrete Vorschläge zu möglichen Veränderungen?
 

SteHa

Mitglied
Hallo KonradN!
Vielen Dank für deine Rückmeldung!
Es tut wirklich gut, die Meinung eines Menschen vom Fach zu lesen. Da hat man dann plötzlich ne klare Linie, der man dann folgen kann.
Ich kann deiner Ausführung ziemlich gut folgen und werde das bei Gelegenheit berücksichtigen. Wie gesagt, es ist nur ein Hobby von mir und es steht keinerlei Prüfungs-, Jobdruck dahinter. (im Grunde bin ich nur fasziniert von der Schönheit eines JavaCodes. Das geht soweit, dass ich C# ablehnte, nur weil da die Methodennamen groß geschrieben werden :) ). Das ist die Freiheit eines Hobbyisten.
Und ja, gerne! Wenn ich meine Scheu mal überwinde, werde ich bei weiteren Fragen auch etwas Code von mir posten...
 

KonradN

Super-Moderator
Mitarbeiter
Ja, als Hobbyist sollte der Spaß an erster Stelle stehen.

Aber sobald ein Projekt etwas komplexer wird, ist die Gefahr sehr groß, dass sehr großer Frust entsteht. Man starten und kommt dann irgend wann zu einem Punkt, dass es einfach zu unübersichtlich geworden ist und dass eine Änderung plötzlich sehr komplex wird.

Das ist aber absolut nichts Schlimmes - nur hab im Hinterkopf: Da gibt es diverse Ansätze und Ideen, um sowas zu vermeiden und Du hast ein Forum gefunden, in dem viele hilfsbereite Menschen sind, die gerne ihr Wissen teilen und gerne weiterhelfen. Also ehe zu viel Frust aufkommt: Einfach vorab einmal nachfragen. Denn es ist aus meiner Sicht ein sehr schönes Hobby (das ich zu meinem Beruf machen konnte).
 

AndiE

Top Contributor
Testbarkeit - Bei der Aufteilung bekommst Du Codeteile, die Du für sich testen kannst. Du kannst also die Funktionalität sicher stellen. Vermutlich ist das aber (noch?) kein Thema für Dich.
Nach meine Erfahrung ist dieser Punkt wichtig. Weil die Beschäftigung mit den Prinzipien hinter JUnit und TDD in mir zumindest eine ganz andere Sicht auf das Programmieren geweckt haben, die ich gerne vorher gehabt hätte.

Es geht vereinfacht darum, dass du dich beim Scheiben erst einmal um die Funktionalität eines Programms kümmern kannst.

Für ein Adressbuch kann man z.B. mit so einem (Pseudo)-Code seine Funktion testen, ohne eine Menuführung erstellt zu haben:


Java:
class Adressliste al= new Adessliste();
f= new Contact("Hans Franz","01234567890");
al.add(f);
f=new Contact("Susi Sorglos","0311 123456");
al.add(f);
al.listAll(); //Gibt alle Eintäge aus

Ich selbst empfinde das Buch zu BlueJ gut, weil es gut die Eigenheiten von OOP überbingt.
 

Manul

Mitglied
Für ein Adressbuch kann man z.B. mit so einem (Pseudo)-Code seine Funktion testen, ohne eine Menuführung erstellt zu haben:
Java:
class Adressliste al= new Adessliste();
f= new Contact("Hans Franz","01234567890");
al.add(f);
f=new Contact("Susi Sorglos","0311 123456");
al.add(f);
al.listAll(); //Gibt alle Eintäge aus
Und wo genau ist da der Test?
 

Barista

Top Contributor
Also bitte, bitte!
Gerne auch abstract...
Ist das eine Frage?

Wenn der gesamte Code generiert ist, was hast Du dann eigentlich geleistet und was willst Du erreichen?

Meine Kinder haben vor vielen Jahren mal eine Elektro-Orgel geschenkt bekommen, da waren Lieder zu Abspielen gespeichert. Ich glaube, das Abspielen dieser Lieder am Geburtstag war die einzige Nutzung, dann war das Ding weg:)

Aber egal.

Das Command-Pattern ist schon recht gut.

Weiter unten gibt es dann switches, da fände ich es besser, beim Command-Pattern zu bleiben.

Die Ziffer für den Menüpunkt könnte man per Programm erzeugen ( von 1 bis 9, bei mehr Menüpunkten dann Buchstaben).

Du könntest die ganze Menüstruktur in eine TreeMap packen.

Das wären meine Ideen.

Den Scanner würde ich an einer einzigen Stelle im Code Instanziieren (Erzeugen), public static, schliesslich hast Du nur eine Tastatur am Rechner.
 

Blender3D

Top Contributor
Ich kann den Code nachvollziehen. Abgesehen davon, dass das mit Kanonen auf Spatzen schießen ist, für mein kleines Programm.
Also bitte, bitte!
Die Idee ist es, falls ich das richtig verstanden habe, für jeden Menüpunkt eine Kommandoklasse zu Verfügung zu stellen, die das Command Interface implementiert.
Der Aufrufer ist dann der jeweilige Menüpunkt.
Verbesserungsvorschläge für deinen Code:
1) In deinem Beispiel kommt es mehrfach zu redundantem Code.
a) switch case wird durch das Command Interface eigentlich überflüssig.
b) Der Kontrollmechanismus und die Anzeige für das Menü sind mehrfach vorhanden.
2) Scanner
a) Ein Scanner Objekt genügt.
b) Eingabe von ganzen Zahlen Benutzerfehler abfangen falls z.B. ein String statt einer Zahl eingegeben wird.

Ich habe den Code etwas überarbeitet und in folgende Klassen aufgeteilt.
Menu
Zeigt das Menü an und wartet auf die Benutzereingabe.
MenuItem
Ist der Aufrufer des jeweiligen Kommandos.
MenuCtrl
Steuert den Wechsel zwischen den Menüs.
Command
Das Interface das die aufzurufenden Klassen implementieren.
Input
Ermöglicht die Eingabe des gewählten Menüpunktes und fängt etwaige Fehleingaben ab.
TestMenu
Beispiel für die Anwendung der obigen Klassen.
Hier der zugehörige Code.
Java:
public class TestMenu {
    // Namen der Eintraege der Menues
    public static String[] nameMain = { "Hauptoption 1", "Hauptoption 2" };
    public static String[] nameSub1 = { "Unteroption 1.1", "Unteroption 1.2" };
    public static String[] nameSub2 = { "Unteroption 2.1", "Unteroption 2.2", "Unteroption 2.3" };

    // Commandos der Einträge der Menues
    public static Command[] cmdMain = { new OptionMain1(), new OptionMain2() };
    public static Command[] cmdSub1 = { new OptionSub1_1(), new OptionSub1_2() };
    public static Command[] cmdSub2 = { new OptionSub2_1(), new OptionSub2_2(), new OptionSub2_3() };

    public static void main(String[] args) {
        Menu[] myMenu = { new Menu("Haupt Menue", nameMain, cmdMain), new Menu("Sub Menue 1", nameSub1, cmdSub1),
                new Menu("Sub Menue 2", nameSub2, cmdSub2) };
        MenuCtrl menu = new MenuCtrl(myMenu);
        menu.doMenu();
        System.out.println("Ende");
    }
}

Du kannst deine aufrufenden Klassen verwenden indem du sie das Command Interface implementieren lässt und sie im jeweiligem Command
Array einfügst.

Java:
import java.util.ArrayList;

public class Menu {

    private ArrayList<MenuItem> menu = new ArrayList<MenuItem>();
    private String title;

    /**
     *
     * @param title Titel des Menues.
     * @param name  Namen der Menue Eintraege.
     * @param cmd   Komandoklassen fuer die Eintraege.
     */
    public Menu(String title, String[] name, Command[] cmd) {
        this.title = title;
        for (int i = 0; i < name.length; i++) {
            MenuItem item = new MenuItem(name[i]);
            menu.add(item);
            if (cmd != null && i < cmd.length)
                item.setCmd(cmd[i]);
        }
    }

    /**
     * Zeigt das Menue an und wartet auf die Benuztereingabe.
     *
     * @return Gewaehlter Eintrag.
     */
    public int doMenu() {
        int exit = getExitNumber();
        printSerperator();
        System.out.println("->\t" + title);
        printSerperator();
        System.out.print(this);
        System.out.println(exit + ".\t" + "Exit");
        printSerperator();
        System.out.print("> ");
        int choice = Input.Integer(exit);
        if (choice != exit)
            menu.get(choice).execute();
        return choice;
    }

    private int getExitNumber() {
        return menu.size();
    }

    public boolean isExit(int id) {
        return id == getExitNumber();
    }

    private static void printSerperator() {
        System.out.println("------------------------");
    }

    @Override
    public String toString() {
        StringBuffer tmp = new StringBuffer();
        for (int i = 0; i < menu.size(); i++)
            tmp.append(i + ".\t" + menu.get(i) + System.lineSeparator());
        return tmp.toString();
    }
}
Java:
public class MenuItem implements Command {
    private String name;
    private Command cmd;

    public MenuItem(String name) {
        this.name = name;
    }

    @Override
    public void execute() {
        if (cmd != null)
            cmd.execute();
    }

    public Command getCmd() {
        return cmd;
    }

    public void setCmd(Command cmd) {
        this.cmd = cmd;
    }

    @Override
    public String toString() {
        return name;
    }
}
Java:
public class MenuCtrl {
    private final static int MAIN = 0; // Hauptmenue ist der erste Eintrag im Array
    private final static int NO_COMMAND = -1;
    private Menu[] menu;

    public MenuCtrl(Menu[] menu) {
        this.menu = menu;
    }

    /**
     * Steuert den Wechsel zwischen den Menues.
     */
    public void doMenu() {
        int menuId = MAIN;
        int cmd = NO_COMMAND;
        while (!isExit(menuId, cmd)) {
            cmd = menu[menuId].doMenu();
            if (menuId == MAIN) {
                if (!menu[menuId].isExit(cmd))
                    menuId = cmd + 1;
            } else if (menu[menuId].isExit(cmd)) {
                menuId = MAIN;
                cmd = NO_COMMAND;
            }
        }     
    }

    private boolean isExit(int menuId, int cmd) {
        return menuId == MAIN && menu[menuId].isExit(cmd);
    }
}
Java:
public interface Command {
    public void execute();
}
Java:
import java.util.Scanner;

public class Input {
    private static Scanner input = new Scanner(System.in);

    /**
     * Liest einen Integerwert vom Scanner ein im Bereich von 0 - max.<br>
     * Faengt ungueltige Eingaben ab.
     *
     * @param max
     * @return Die eingegebene Zahl
     */
    public static int Integer(int max) {
        int value = 0;
        boolean ok = false;
        do {
            try {
                value = Integer.parseInt(input.next());
                if (value < 0 || value > max)
                    System.out.println("Bitte eine ganze Zahl von 0-" + max + " eingeben!");
                else
                    ok = true;
            } catch (NumberFormatException e) {
                System.out.println("Bitte eine ganze Zahl eingeben!");
            }
        } while (!ok);
        return value;
    } 
}
Beispiel für eine Kommando Klasse.
Java:
public class OptionMain1 implements Command {
    @Override
    public void execute() {
        System.out.println("\tGehe zu Sub 1");
    }
}
 
Zuletzt bearbeitet:

Blender3D

Top Contributor
Der Thread-Ersteller wollte doch wahrscheinlich Hilfe zur Selbsthilfe.
Also ich entnehme seinem Post, dass er bereits ein fertiges kleines Programm hat für das er ein über die Konsole gesteuerte Menü benötigt.
Er hat dafür bereits die Windows KI Copilot benutzt und obiges Ergebnis erhalten.
Da das Ergebnis nicht wirklich brauchbar war hat er um Hilfe gebeten.
Ich habe deswegen obigen Code etwas überarbeitet.
Mein Beispielcode muss immer noch mit seinem Programm verknüpft werden.
Das sollte zwar einfacher gehen als mit dem KI Code. Dennoch steckt noch einige Arbeit und Verstehen des Codes dahinter.
 

SteHa

Mitglied
Hallo! Vielen Dank an alle die hier gekostet haben!
@Blendet3D: sowas wie dein Code habe ich mir gewünscht. Das meinte ich am Anfang mit: gerne auch etwas abstrakter... ich werde ihn mit Genuss auseinandernehmen und studieren.
...und nein, eine funktionierende Menüführung habe ich schon. Halt der ganz normale Standard, der in jedem Anfängerbuch drinsteht. Switch/case in der mainmethode und von da aus verschiedene staticMethoden anspringen. Auch den Scanner als public static. Da ich etwas an den DesignPatterns rumgelesen habe, fragte ich aus Neugierde den CoPiloten wie er denn das DesignPatterntechnisch lösen würde.
Also alles im grünen Bereich und danke für deinen Code....
 

M.L.

Top Contributor
DesignPatterns ... CoPiloten
Generell dienen z.B. DesignPatterns (wie z.B. Command) dem Menschen um (häufige) Änderungen oder Erweiterungen an einer (zentralen) Stelle leicht(er) durchführen zu können. Den Compiler interessiert nur die formelle Korrektheit des Codes, weder dessen Lesbarkeit, noch dessen Aufteilung, noch wer diesen wie kreiert oder ob am Bildschirm z.B. ein Menü angeboten wird.
 

SteHa

Mitglied
Generell dienen z.B. DesignPatterns (wie z.B. Command) dem Menschen um (häufige) Änderungen oder Erweiterungen an einer (zentralen) Stelle leicht(er) durchführen zu können. Den Compiler interessiert nur die formelle Korrektheit des Codes, weder dessen Lesbarkeit, noch dessen Aufteilung, noch wer diesen wie kreiert oder ob am Bildschirm z.B. ein Menü angeboten wird.
...Danke, du sagst es. Ich wollte das auch so mal hier in der Öffentlichkeit ausbreiten. Ich habs gelassen.
Das alles macht Sinn für Profiprogrammierer. Für ganz große Projekte... da war meine Schlussfolgerung doch nicht so ganz falsch
...egal, ich werde dem Blender3D seinen Code trotzdem gerne erforschen..
Die Idee ist es, falls ich das richtig verstanden habe, für jeden Menüpunkt eine Kommandoklasse zu Verfügung zu stellen, die das Command Interface implementiert.
Der Aufrufer ist dann der jeweilige Menüpunkt.
Verbesserungsvorschläge für deinen Code:
1) In deinem Beispiel kommt es mehrfach zu redundantem Code.
a) switch case wird durch das Command Interface eigentlich überflüssig.
b) Der Kontrollmechanismus und die Anzeige für das Menü sind mehrfach vorhanden.
2) Scanner
a) Ein Scanner Objekt genügt.
b) Eingabe von ganzen Zahlen Benutzerfehler abfangen falls z.B. ein String statt einer Zahl eingegeben wird.

Ich habe den Code etwas überarbeitet und in folgende Klassen aufgeteilt.
Menu
Zeigt das Menü an und wartet auf die Benutzereingabe.
MenuItem
Ist der Aufrufer des jeweiligen Kommandos.
MenuCtrl
Steuert den Wechsel zwischen den Menüs.
Command
Das Interface das die aufzurufenden Klassen implementieren.
Input
Ermöglicht die Eingabe des gewählten Menüpunktes und fängt etwaige Fehleingaben ab.
TestMenu
Beispiel für die Anwendung der obigen Klassen.
Hier der zugehörige Code.
Java:
public class TestMenu {
    // Namen der Eintraege der Menues
    public static String[] nameMain = { "Hauptoption 1", "Hauptoption 2" };
    public static String[] nameSub1 = { "Unteroption 1.1", "Unteroption 1.2" };
    public static String[] nameSub2 = { "Unteroption 2.1", "Unteroption 2.2", "Unteroption 2.3" };

    // Commandos der Einträge der Menues
    public static Command[] cmdMain = { new OptionMain1(), new OptionMain2() };
    public static Command[] cmdSub1 = { new OptionSub1_1(), new OptionSub1_2() };
    public static Command[] cmdSub2 = { new OptionSub2_1(), new OptionSub2_2(), new OptionSub2_3() };

    public static void main(String[] args) {
        Menu[] myMenu = { new Menu("Haupt Menue", nameMain, cmdMain), new Menu("Sub Menue 1", nameSub1, cmdSub1),
                new Menu("Sub Menue 2", nameSub2, cmdSub2) };
        MenuCtrl menu = new MenuCtrl(myMenu);
        menu.doMenu();
        System.out.println("Ende");
    }
}

Du kannst deine aufrufenden Klassen verwenden indem du sie das Command Interface implementieren lässt und sie im jeweiligem Command
Array einfügst.

Java:
import java.util.ArrayList;

public class Menu {

    private ArrayList<MenuItem> menu = new ArrayList<MenuItem>();
    private String title;

    /**
     *
     * @param title Titel des Menues.
     * @param name  Namen der Menue Eintraege.
     * @param cmd   Komandoklassen fuer die Eintraege.
     */
    public Menu(String title, String[] name, Command[] cmd) {
        this.title = title;
        for (int i = 0; i < name.length; i++) {
            MenuItem item = new MenuItem(name[i]);
            menu.add(item);
            if (cmd != null && i < cmd.length)
                item.setCmd(cmd[i]);
        }
    }

    /**
     * Zeigt das Menue an und wartet auf die Benuztereingabe.
     *
     * @return Gewaehlter Eintrag.
     */
    public int doMenu() {
        int exit = getExitNumber();
        printSerperator();
        System.out.println("->\t" + title);
        printSerperator();
        System.out.print(this);
        System.out.println(exit + ".\t" + "Exit");
        printSerperator();
        System.out.print("> ");
        int choice = Input.Integer(exit);
        if (choice != exit)
            menu.get(choice).execute();
        return choice;
    }

    private int getExitNumber() {
        return menu.size();
    }

    public boolean isExit(int id) {
        return id == getExitNumber();
    }

    private static void printSerperator() {
        System.out.println("------------------------");
    }

    @Override
    public String toString() {
        StringBuffer tmp = new StringBuffer();
        for (int i = 0; i < menu.size(); i++)
            tmp.append(i + ".\t" + menu.get(i) + System.lineSeparator());
        return tmp.toString();
    }
}
Java:
public class MenuItem implements Command {
    private String name;
    private Command cmd;

    public MenuItem(String name) {
        this.name = name;
    }

    @Override
    public void execute() {
        if (cmd != null)
            cmd.execute();
    }

    public Command getCmd() {
        return cmd;
    }

    public void setCmd(Command cmd) {
        this.cmd = cmd;
    }

    @Override
    public String toString() {
        return name;
    }
}
Java:
public class MenuCtrl {
    private final static int MAIN = 0; // Hauptmenue ist der erste Eintrag im Array
    private final static int NO_COMMAND = -1;
    private Menu[] menu;

    public MenuCtrl(Menu[] menu) {
        this.menu = menu;
    }

    /**
     * Steuert den Wechsel zwischen den Menues.
     */
    public void doMenu() {
        int menuId = MAIN;
        int cmd = NO_COMMAND;
        while (!isExit(menuId, cmd)) {
            cmd = menu[menuId].doMenu();
            if (menuId == MAIN) {
                if (!menu[menuId].isExit(cmd))
                    menuId = cmd + 1;
            } else if (menu[menuId].isExit(cmd)) {
                menuId = MAIN;
                cmd = NO_COMMAND;
            }
        }    
    }

    private boolean isExit(int menuId, int cmd) {
        return menuId == MAIN && menu[menuId].isExit(cmd);
    }
}
Java:
public interface Command {
    public void execute();
}
Java:
import java.util.Scanner;

public class Input {
    private static Scanner input = new Scanner(System.in);

    /**
     * Liest einen Integerwert vom Scanner ein im Bereich von 0 - max.<br>
     * Faengt ungueltige Eingaben ab.
     *
     * @param max
     * @return Die eingegebene Zahl
     */
    public static int Integer(int max) {
        int value = 0;
        boolean ok = false;
        do {
            try {
                value = Integer.parseInt(input.next());
                if (value < 0 || value > max)
                    System.out.println("Bitte eine ganze Zahl von 0-" + max + " eingeben!");
                else
                    ok = true;
            } catch (NumberFormatException e) {
                System.out.println("Bitte eine ganze Zahl eingeben!");
            }
        } while (!ok);
        return value;
    }
}
Beispiel für eine Kommando Klasse.
Java:
public class OptionMain1 implements Command {
    @Override
    public void execute() {
        System.out.println("\tGehe zu Sub 1");
    }
}
Hallo Blender3D!
Ich habe jetzt deinen Code in Eclipse geladen und soweit angepasst dass es läuft.
Soviel Codeverständnis habe ich doch, GottseiDank!
Darf ich mal fragen: Das hast du doch, zwischen zwei Kaffees, kurz mal so runtergetippselt, oder?
Respekt!
 

Blender3D

Top Contributor
Hallo Blender3D!
Ich habe jetzt deinen Code in Eclipse geladen und soweit angepasst dass es läuft.
Soviel Codeverständnis habe ich doch, GottseiDank!
Bravo und Respekt für deinen Erfolg.:cool:
Das zeigt, dass du dich in Code einlesen und in weiterverwenden kannst. Eine wichtige Fähigkeit eines guten Programmierers.
Darf ich mal fragen: Das hast du doch, zwischen zwei Kaffees, kurz mal so runtergetippselt, oder?
Respekt!
Also in "zwischen 2 Kaffee", habe ich das nicht hinbekommen. Da überschätzt du meine Fähigkeiten. Das Tippen selbst geht zwar recht rasch dank Eclipse der IDE die ich benutzte. Aber um die Zeit für so etwas zu messen, muss man auch den Aufwand der Analyse des Problems mit einberechnen. Ich habe dafür insgesamt etwas mehr als 30 Minuten gebraucht. Sicher gibt es Programmierer, die das viel schneller hinbekommen. Ich gehöre da leider nicht dazu.
Meiner Meinung nach sollte man sich aber generell für die Analyse des zu bewältigen Problems genügend Zeit einräumen und nicht einfach so darauf los programmieren. ;)
Die KI Copilot hat den von dir geposteten Code wahrscheinlich noch schneller als "zwischen 2 Kaffee" geliefert.
Das Resultat war dafür aber auch nicht wirklich brauchbar.
Siehe
https://www.java-forum.org/thema/bitte-ratschlaege-fuer-console-menufuehrung.204739/#post-1374081
Aber vielen Dank für dein Lob :) .
 

KonradN

Super-Moderator
Mitarbeiter
Ich habe mal bereinigt. So keine Konsolen-Anwendung gewünscht wird, dann haben die UI Frameworks eigene Klassen für Menüs. Die haben dann natürlich auch die Baumstruktur bereits abgebildet, so dass man keine eigene Klasse Tree oder so benötigt. Wenn das interessant ist: Dazu gibt es genug Seiten mit Beschreibung incl. Beispiele. Daher dürfte durch das Entfernen dieser Off Topic Posts nichts verloren gegangen sein.

Sollte es zu dem Thema aber Diskussionsbedarf geben: Bitte eigenen Thread erstellen.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
ineedhelpinjava OOP Bitte wichtig Java Basics - Anfänger-Themen 6
G Bitte meinen Account löschen Java Basics - Anfänger-Themen 1
D Bitte um Hilfe muss es schnellstmöglich erledigen Java Basics - Anfänger-Themen 15
I Bitte um Hilfe zu unterstehenden Code Java Basics - Anfänger-Themen 6
M Bitte um Hilfe bei 2DArrays Java Basics - Anfänger-Themen 8
D Abrechnung bitte um hilfe Java Basics - Anfänger-Themen 25
Vivien Bitte um Optimierungsvorschläge / Verbesserungsvorschläge / allgemeines Feedback Java Basics - Anfänger-Themen 8
J Doppelt verkette Liste ich bitte um Hilfe Java Basics - Anfänger-Themen 4
J Java List, Bitte um Hilfe Java Basics - Anfänger-Themen 15
J Java List, bitte um Hilfe Java Basics - Anfänger-Themen 3
pry bitte Hilfe beim Kreditrechner objektorientiert Java Basics - Anfänger-Themen 6
marcooooo einmal noch schnell hilfe bitte:/ Java Basics - Anfänger-Themen 2
F Methoden Bitte Helft mir meinen Fehler zu finden. Möchte in diesem Bankenprogramm durch die Konsoleneingabe auswählen welches Konto reduziert und welches erhö Java Basics - Anfänger-Themen 17
I Methoden char Array Aufgabe (bitte hierbei um Hilfe) Java Basics - Anfänger-Themen 3
ZH1896ZH OOP Verstehe nicht was der Hinweis bedeutet, bitte um Hilfe! Java Basics - Anfänger-Themen 2
B BITTE!! Ich brauche dringende Hilfe bei einer Aufgabe Java Basics - Anfänger-Themen 17
S Bitte Hilfe zu Fehlermeldung am Handy Java Basics - Anfänger-Themen 2
I Do-While / Kalkulator / Bitte um Hilfe Java Basics - Anfänger-Themen 9
P Bitte Hinweise zu folgendem "Klassenproblem" Java Basics - Anfänger-Themen 3
M Bitte um Hilfe bei Quellcode (Rekursion) Java Basics - Anfänger-Themen 6
A Erste Schritte Bitte helfen sie mir diese Programm zu schreiben Java Basics - Anfänger-Themen 12
C Stack und Queue in Aktion (Bitte Hilfe für die Klausur) Java Basics - Anfänger-Themen 7
F (Eclipse) Beim importieren etwas fehlerhaft bitte um Hilfe :) Java Basics - Anfänger-Themen 3
B MVC Struktur mit mehreren Szenen - wer schaut mal bitte drüber? Java Basics - Anfänger-Themen 2
T Bitte um Hilfe Java Basics - Anfänger-Themen 9
D Arraylisten sortieren bitte um Hilfe Java Basics - Anfänger-Themen 4
P Erste Schritte Bitte ein paar Erklärungen zu meinem Code Java Basics - Anfänger-Themen 6
J Bitte Hilfe Java Basics - Anfänger-Themen 4
W FileReader - Bitte um Erklärung Java Basics - Anfänger-Themen 7
V Memory Logik Problem/Denkblockade, bitte helft Java Basics - Anfänger-Themen 1
T Bitte um Hilfe bei Aufgabe: Long zahl = Long.parseLong(args [0]); Java Basics - Anfänger-Themen 3
J Bitte um Erklärung Java Basics - Anfänger-Themen 4
A GUI- Allgemeines Problem (Bitte helfen) Java Basics - Anfänger-Themen 15
D Bitte um Hilfe bei "error: package com.apple.eawt does not exist import com.apple.eawt.*;" Java Basics - Anfänger-Themen 1
C Polymorphie - Erklärung bitte Java Basics - Anfänger-Themen 5
M Quadrat zeichnen einfach bitte! Java Basics - Anfänger-Themen 2
F Bitte mal Zusammenhänge der Klassen erklären Java Basics - Anfänger-Themen 8
P <identifier> expected Fehler bitte um Hilfe Java Basics - Anfänger-Themen 5
J Kann mir bitte mal jemand diese Codes erklären? Java Basics - Anfänger-Themen 19
J Threading-Aufgabe. Totale Noob Fragen, aber bitte trotzdem beantworten ;) Java Basics - Anfänger-Themen 7
O Rundungsfehler bitte erklären! Java Basics - Anfänger-Themen 4
K NullPointerException wird geworfen, bitte um Hilfe! Java Basics - Anfänger-Themen 7
M Erklärung Code Mergesort Bitte Java Basics - Anfänger-Themen 3
N While Schleife Erklärung Bitte Java Basics - Anfänger-Themen 3
S Variablen Hilfe bitte Java Basics - Anfänger-Themen 6
Z Erste Schritte Bitte helft mir dringend!! Java Basics - Anfänger-Themen 3
T Unit tests fehlerhaft bitte um hiiiiilfe :D Java Basics - Anfänger-Themen 1
J Ich bitte DRINGEND um Hilfe!!! Java Basics - Anfänger-Themen 16
Q Importieren meiner Boundary? Bitte Hilfe Java Basics - Anfänger-Themen 3
T Eine kurze frage vor der prüfung bitte. Java Basics - Anfänger-Themen 5
CyberFish initialisieren, obwohl es gemacht wurde! Bitte um Hilfe Java Basics - Anfänger-Themen 10
H Bitte um Hilfe von Profis. Java Basics - Anfänger-Themen 5
S Klassen Formel zur Berechnung .... Bitte um Hilfe Java Basics - Anfänger-Themen 7
H Methoden Bitte um Erklärung der askString-Methode Java Basics - Anfänger-Themen 15
J Probleme bei kompilieren ... Bitte um Hilfe Java Basics - Anfänger-Themen 27
O Erste Schritte Aller Anfang ist schwer ! Bitte um Unterstützung Java Basics - Anfänger-Themen 6
G Bitte um Erklärung dieser einer Zeile Java Basics - Anfänger-Themen 5
P Bitte um hilfe bei einfachem Rechner Java Basics - Anfänger-Themen 7
B Bitte Hilfe für Funktionalität eines Sudokus Java Basics - Anfänger-Themen 8
G Brauche bitte Hilfe, bei umgekehrter Ausgabe!! Java Basics - Anfänger-Themen 6
G Input/Output FilenameFilter aber bitte keine Unterordner Java Basics - Anfänger-Themen 5
J Vererbung Anfänger Programm bitte um Kritik&Anregungen Java Basics - Anfänger-Themen 21
N Bitte Java Basics - Anfänger-Themen 2
D ???:L Bitte einmal mit drüber nachdenken Java Basics - Anfänger-Themen 5
eLogic DownloadManager - Bitte helft mir Java Basics - Anfänger-Themen 7
R Vererbung Bitte um Erklärung - Instanzvariablen Java Basics - Anfänger-Themen 8
U finde fehler nicht! bitte um hilfe Java Basics - Anfänger-Themen 8
M Problem: code too large - bitte um Hilfe Java Basics - Anfänger-Themen 12
U Bitte Helfen kleines Spiel Java Basics - Anfänger-Themen 9
B Java und Javac funktionieren nicht - bitte hilfe Java Basics - Anfänger-Themen 5
P Bitte helft mir Java Basics - Anfänger-Themen 3
3 Bitte um Hilfe bei Lösung einer Aufgabe Java Basics - Anfänger-Themen 16
M Aus CSV-Datei lesen und anzeigen (bitte schnell um Antwort) Java Basics - Anfänger-Themen 6
R Jave Problem... bitte um Hilfe!! Java Basics - Anfänger-Themen 6
S Java problem, bitte um hilfe! Java Basics - Anfänger-Themen 9
B Bitte um Hilfe es geht um Array + Punkte wie Dreieck,Fläche etc. Java Basics - Anfänger-Themen 12
C Bitte kurzes Feedback - JavaVersionen Java Basics - Anfänger-Themen 6
M Bitte um Verbesserungsvorschläge Java Basics - Anfänger-Themen 14
N verständniss problem bitte um hilfe Java Basics - Anfänger-Themen 3
L Brauche bitte dringend Hilfe für Klausur Java Basics - Anfänger-Themen 8
B Monat und Jahr bitte um Hilfe Java Basics - Anfänger-Themen 8
J Datentypen Generics - Bitte helfen !! Java Basics - Anfänger-Themen 9
T Java Beispiel Bitte helft mir Java Basics - Anfänger-Themen 5
A Dringende Bitte um Erklärungen zum besseren Verständnis Java Basics - Anfänger-Themen 4
D Java Problem bitte um hilfe Java Basics - Anfänger-Themen 4
S Datei-KopierProgramm ? CODE BITTE VERBESSERN Java Basics - Anfänger-Themen 11
D code erklären bitte ! Java Basics - Anfänger-Themen 15
Rudolf Verstehe das Ergebnis nicht - bitte erklären Java Basics - Anfänger-Themen 7
M Kann mir bitte jemand "java.util.ArrayList" erklären? Java Basics - Anfänger-Themen 5
M Bitte um Kontrolle meines Quelltextes Java Basics - Anfänger-Themen 10
J Leichte Java Anfängerfrage. Bitte schnelle Antwort. :) Java Basics - Anfänger-Themen 10
S BITTE UM HILFE: Unterschied Deklaration und Signatur einer Methode Java Basics - Anfänger-Themen 3
S BITTE UM HILFE HASHTABLE/import java.util.Hashtable in Ecplipse Java Basics - Anfänger-Themen 12
T Problem mit Aufgabe..bitte um Hilfe Java Basics - Anfänger-Themen 8
G Bitte um Erklärung Java Basics - Anfänger-Themen 9
K 50 errormeldungen- komme auch nach vielen Nachmittagen nicht weiter. bitte helfen Java Basics - Anfänger-Themen 39
D Ausgabe sauber formatieren *bitte nochmal reinschaun* Java Basics - Anfänger-Themen 7
S Bitte um Hilfe beim unsortierten Binärbaum!! Java Basics - Anfänger-Themen 6
D Ausgabe in Datei ( bitte helfen ) Java Basics - Anfänger-Themen 13
-horn- Bitte: Wie besondere Daten auslesen und umspeichern? Java Basics - Anfänger-Themen 3

Ähnliche Java Themen

Neue Themen


Oben