Swing Zuständigkeit, Delegation, Kapselung ?!

kaoZ

Top Contributor
Aloha, hier mal eine kleine Frage bezüglich der Konstruktion einer JMenuBar, was macht mehr sinn / ist die Sauberere Lösung ?

Beispiel Ansatz I: ( gekapselt in einer Methode )

Java:
private JMenuBar createMenuBar(){
		JMenuBar menuBar = new JMenuBar();
		String[] entrys = {"Datei", "Bearbeiten", "Suchen", "Einstellungen", "Daten", "Fenster", "Hilfe"};
		
		for (int i = 0; i < entrys.length; i++) {
			menuBar.add(new JMenu(entrys[i]));
		}
		return menuBar;
	}

Der dazugehörige Aufruf im Konstruktor wäre dann
Java:
bar = createMenuBar();

oder in die Realisierung in einer Separaten klasse, hier mal nicht abgeleitet ?

Beispiel Ansatz II:

Java:
package de.kaoz.components;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class SimpleJMenuBar {
	
	JMenuBar bar;
	JMenu fileMenu, editMenu, optionMenu, searchMenu, dataMenu, windowMenu, helpMenu;
	JMenuItem file, open, save, saveTo, importFile, exportFile, close;
	
	public SimpleJMenuBar() {
		initialise();
		addToBar();
	}
	
	private void initialise(){
		
		bar = new JMenuBar();
		
		fileMenu = new JMenu("Datei");
		editMenu = new JMenu("Bearbeiten");
		optionMenu = new JMenu("Einstellungen");
		searchMenu = new JMenu("Suchen");
		dataMenu = new JMenu("Daten");
		windowMenu = new JMenu("Fenster");
		helpMenu = new JMenu("Hilfe");
		
		file = new JMenuItem("Neu...");
		open = new JMenuItem("Öffnen...");
		save = new JMenuItem("Speichern...");
		saveTo = new JMenuItem("Speichern unter...");
		importFile = new JMenuItem("Importieren...");
		exportFile = new JMenuItem("Exportieren...");
		close = new JMenuItem("Beenden...");
	}
	
	private void addToBar(){
			fileMenu.add(file);
			fileMenu.add(open);
			fileMenu.addSeparator();
			fileMenu.add(save);
			fileMenu.add(saveTo);
			fileMenu.addSeparator();
			fileMenu.add(importFile);
			fileMenu.add(exportFile);
			fileMenu.addSeparator();
			fileMenu.add(close);
		bar.add(fileMenu);
		
		bar.add(editMenu);
		bar.add(optionMenu);
		bar.add(searchMenu);
		bar.add(dataMenu);
		bar.add(windowMenu);
		bar.add(helpMenu);
	}
	
	public JMenuBar getBar(){
		return this.bar;
	}

}

Der dazugehörige Aufruf im Konstruktor wäre dann
Java:
bar = new SimpleJMenuBar().getBar();

Die Frage ist jetzt , was macht vom Aufbau her mehr Sinn ? , Variante II ist definitiv die Lösung die mehr Zeit in Anspruch nimmt, allerdings ist es so denke ich auch einfacher nachher die Eventbehandlung anzugehen, da ich auch eigene Setter anbieten kann die mir gewisse Komponenten liefern, oder ich einfach eine innere Klasse als Listener definieren kann.

Was meint ihr ?
 
Zuletzt bearbeitet:

TheSorm

Bekanntes Mitglied
In dem fall würde ich sagen Methode 1.Beim Menüs sind wenn du die von Java wie gezeicgt verwendest getter setter und alles ander schon vordefinirt, deswegen ist die erste methode platzsparender und sauberer die 2te ist meiner meinung anch aufgrund der java mitgeliferten Methoden überflüssig umstendlich. Wenn du jetzt natürlich 100 geschachtelte Menüs hast ist Methode 2 erstmal übersichtlicher aber Methode 1 tut es trotzdem noch. Die zweite Methode macht aber auch sinn ich denke du soltest die erste Methode mit der zweiten Verbinden also zur übersicht auslagern aber trz so klein wie möglich halten wenn du estwas spezielleres Brauchst kanst dieses am besten aus einer ArrayList oder sonstiges herraus wieder bekommen.
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Sowas ähnliches hatte ich mir auch schon überlegt,

was ich definitiv machen werde ist die MenuBar in einer eigenen Klasse zu definieren und lediglich dort wo ich diese Bar setzen möchte eine Instanz zu erzeugen,

die Fragen die sich mir dann stellen sind :

1. wie realisiere ich die Listener ( geplant : ebenfalls eigenständige Klasse ) Controller (MVC)?!
2. Wie delegiere ich die Aufrufe durch den Listener an den jeweiligen Panel

[EDIT]Ich probiere grade etwas rum , zzt. sieht es folgendermaßen aus :[/EDIT]

Java:
public class SimpleMenuBar extends JMenuBar {
	private static final long serialVersionUID = 1L;
	
	JMenu[] entrys;
	JMenuItem[] fileItems;
	
	public SimpleMenuBar() {
		createMenu("Datei", "Bearbeiten", "Einstellungen", "Suchen", "Fenster", "Hilfe");
		createItems();
	}
	
	private void createMenu(String...strings){
		entrys = new JMenu[strings.length];
		
		for (int i = 0; i < strings.length; i++) {
			entrys[i] = new JMenu(strings[i]);
		}
		
		for (JMenu entry : entrys) {
			this.add(entry);
		}
	}

	private void createItems(){
		JMenu file = new JMenu("Neu...");
		JMenuItem invoice = new JMenuItem("Rechnung");
		JMenuItem estimate = new JMenuItem("Kostenvoranschlag");
		JMenuItem open = new JMenuItem("Öffnen...");
		JMenuItem save = new JMenuItem("Speichern...");
		JMenuItem saveUnder = new JMenuItem("Speichern unter...");
		JMenuItem importFile = new JMenuItem("Importieren...");
		JMenuItem exportFile = new JMenuItem("Exportieren...");
		JMenuItem close = new JMenuItem("Beenden...");
		JMenuItem[] fileItems = {invoice, estimate, open, save, saveUnder, importFile, exportFile, close};
		this.fileItems = fileItems;
		
		file.add(invoice);
		file.add(estimate);
	
		entrys[0].add(file);
		entrys[0].add(open);
		entrys[0].addSeparator();
		entrys[0].add(save);
		entrys[0].add(saveUnder);
		entrys[0].addSeparator();
		entrys[0].add(importFile);
		entrys[0].add(exportFile);
		entrys[0].addSeparator();
		entrys[0].add(close);
		
	}
}
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Andere Überlegung wäre ich Kapsel die einzelnen Menüeinträge jeweils in eigene Methoden

ala :

Java:
createFileMenu(){...}
createEditMenu(){...}
createOptionMenu(){...}

...

das würde zumindest die Kapselung und Zuständigkeit erhöhen,
so könnte ich dann für jedes Menu bzw. dessen Items ein Array als Globale Variable anlegen um später zugriff darauf zu bekommen und z.B Listener hinzuzufügen.

Was meinst du ?! Was wäre die bessere Wahl ?

zu guter letzt dann eine Methode die im Konstruktor dann alles der Bar hinzufügt :

Java:
public SimpleMenuBar(){
 addToBar();
}

//---------------------------

public void addToBar(){
this.add(createFileMenu());
this.add(createEditMenu());
this.add(createOptionMenu()));

...

}
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Ich glaube das hier sieht ganz gut aus soweit , auch von der Kapselung der Daten und der Zuständigkeit her

Java:
package de.kaoz.components;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import static de.kaoz.constants.Constants.*;

public class SimpleMenuBar extends JMenuBar {
	private static final long serialVersionUID = 1L;
	
	JMenu file, edit, option, search, window, help;
	
	public SimpleMenuBar() {
		file = createFileMenu();
		edit = createEditMenu();
		addToBar();
	}
	
	private JMenu createFileMenu(){
		JMenu file = new JMenu(MENUBAR_FILE);
		JMenu newFile = new JMenu("Neu...");
		
		JMenuItem invoice 		= new JMenuItem("Rechnung");
		JMenuItem estimate 		= new JMenuItem("Kostenvoranschlag");
		JMenuItem open 			= new JMenuItem("Öffnen...");
		JMenuItem save 			= new JMenuItem("Speichern");
		JMenuItem saveUnder		= new JMenuItem("Speichern unter...");
		JMenuItem importFile 	= new JMenuItem("Importieren...");
		JMenuItem exportFile 	= new JMenuItem("Exportieren...");
		JMenuItem close			= new JMenuItem("Beenden");
		
		newFile.add(invoice);
		newFile.add(estimate);
		
		file.add(open);
		file.addSeparator();
		file.add(save);
		file.add(saveUnder);
		file.addSeparator();
		file.add(importFile);
		file.add(exportFile);
		file.addSeparator();
		file.add(close);
		
		return file;
	}
	
	private JMenu createEditMenu(){
		JMenu edit = new JMenu(MENUBAR_EDIT);
		
		JMenuItem rollback 		= new JMenuItem("Rückgängig machen");
		JMenuItem stepForward 	= new JMenuItem("Wiederholen");
		JMenuItem cut 			= new JMenuItem("Ausschneiden");
		JMenuItem selectAll 	= new JMenuItem("Alles auswählen");
		JMenuItem copy 			= new JMenuItem("Kopieren");
		JMenuItem paste			= new JMenuItem("Einfügen");
		JMenuItem delete	 	= new JMenuItem("Löschen");
		
		edit.add(rollback);
		edit.add(stepForward);
		edit.addSeparator();
		edit.add(selectAll);
		edit.add(cut);
		edit.add(copy);
		edit.add(paste);
		edit.addSeparator();
		edit.add(delete);
		
		return edit;
	}
	
	private void addToBar(){
		this.add(this.file);
		this.add(this.edit);
	}
	
}

man könnte jetzt sicher noch hergehen und die Magic Strings in eine Separate Datei auslagern, aber das wäre zum jetzigen Standpunkt eher zu zeitaufwändig,

Desweiteren könnte man jetzt hergehen und eben die einzelnen JMenuItems in einer Schleife erzeugen, hinzufügen müsste ich sie dem JMenu allerdings trotzdem von Hand, alleine Schon durch den Einsatz der Separatoren.

Was meint Ihr ?
 
Zuletzt bearbeitet:

TheSorm

Bekanntes Mitglied
Also das auszulagern ist denk ich gut und dann einfach:

Java:
	private class actionListener implements ActionListener {
		
		@Override
		public void actionPerformed(ActionEvent e) {}

so deinen listener aufbaun natürlich vorher auf die einzelnden teile adden. Dann kanst du inherhalb der aufrufe wieder andere Objekte aufrufen die dann das amchen was du wilst an der stelle aus das wäre sehr übersichtlich.
 

kaoZ

Top Contributor
Nur falls es dich Interessieren sollte, ich bastel grade an einem anderen Ansatz:

Java:
package de.kaoz.components;

import java.util.ArrayList;

import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;

	/**
	 * 
	 * @author kaoZ
	 *
	 */

public class SimpleMenuBar extends JMenuBar {
	private static final long serialVersionUID = 1L;
	
	ArrayList<JMenu> entrys;
	ArrayList<JMenuItem> items;
	
	{
		entrys = new ArrayList<>();
		items = new ArrayList<>();
	}
	
	public SimpleMenuBar(String...strings) {
		for (String string : strings) {
			entrys.add(new JMenu(string));
		}
		addToBar();
	}
	
	private void addToBar(){
		for (JMenu menu : entrys) {
			this.add(menu);
		}
	}
	
	public void addItems(int index, ArrayList<JComponent> list){
		for (JComponent jComponent : list) {
			entrys.get(index).add(jComponent);
		}
	}
	
	public ArrayList<JComponent> createMenuItems(String...strings){
		ArrayList<JComponent> list = new ArrayList<>();
		
		for (int i = 0; i < strings.length; i++) {
			
			if(strings[i].equals("Sep_")){
				list.add(new JSeparator());
			}
			else if(strings[i].contains("Sub_")) {
				String[] token = strings[i].substring(4).split("\\*");
				
				JMenu menu = new JMenu(token[0]);
				
				for (int j = 1; j < token.length; j++) {
					menu.add(new JMenuItem(token[j]));
				}
				list.add(menu);
			}
			else{
				list.add(new JMenuItem(strings[i]));
			}
		}
		return list;
	}
}

Das mag auf den ersten Blick etwas Kryptisch aussehen, hat aber Effekt, ich kann jetz über die Methoden , im Gui einfach einzelne Menüs, untermenüs , separatoren und Menuitems erstellen.

bleibt nur noch die funktionalität über den listener zu implementieren, diese sollte aber relativ einfach sein da ich eine Referenz auf die Menüs halte und ggf. noch eine Referenz auf die MenüItems erstellen werde.

Bin atm. ziemlich zufrieden damit, insofern ich mir nicht wieder selbst Steine in den Weg gelegt habe

der Aufbau eines Menüs wäre nun durch folgende Aufrufe möglich :

Java:
menuBar = new SimpleMenuBar("Datei","Bearbeiten","Einstellungen");
	
		ArrayList<JComponent> fileItems = menuBar.createMenuItems("Test", "Sep_", "Öffnen...","Sub_Untermenu*fenster*fenster2", "Fenster", "Speichern");
		ArrayList<JComponent> editItems = menuBar.createMenuItems("Versuch", "Lalala","blub", "Sub_Test*eintrag*zwei*drei", "einstellungen");
		
		menuBar.addItems(0, fileItems);
		menuBar.addItems(1, editItems);

Das wäre z.B in diesem Fall ein Submenü mit 2 weiteren Einträgen :

Java:
"Sub_Untermenu*fenster*fenster2"

[EDIT]Da die Methode
Code:
createMenuItems();
mit Varargs arbeitet könnte ich hier auch einfach ein String Array übergeben ;).[/EDIT]
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
P Problem mit der Kapselung AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben