Swing JMenuBar, Preferences, Properties... und viele andere lustige Dinge (Best Practice)

kaoZ

Top Contributor
Ich Bastel grad auch wieder mal ein wenig an meinen eigenen Projekten :lol:

und wollt mal wissen wie ihr das so handhabt, also mal angenommen wir haben folgende Situation

Java:
import java.util.prefs.Preferences;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import editor.fragments.enums.FileMenu;
import editor.fragments.enums.Menu;

public class Gui{
	
	static Preferences PREFS = Preferences.userNodeForPackage(Gui.class);
	
	private int windowState;
	private JFrame frame;
	private EditorPane pane;
	
	public Gui(){
		initComponents();
		initFrame();
	}
	
	private void initComponents(){
		pane = new EditorPane(this);
	}
	
	private void initFrame(){
		frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.setContentPane(pane);
		frame.setJMenuBar(createMenuBar());
		frame.setExtendedState(getWindowState());
		if(windowState == JFrame.NORMAL) {
			frame.pack();
			frame.setLocationRelativeTo(null);
		}
	}
	
	private JMenuBar createMenuBar(){
		JMenuBar bar = new JMenuBar();
		
//		Menu Entrys
		
		JMenu[] entrys = new JMenu[4];
		for (int i = 0; i < entrys.length; i++) {
			entrys[i] = new JMenu(Menu.values()[i].getValue());
			bar.add(entrys[i]);
		}
		
//		FileMenu Entrys
		
		JMenuItem[] fileEntrys = new JMenuItem[6];
		for (int i = 0; i < fileEntrys.length; i++) {
			fileEntrys[i] = new JMenuItem(FileMenu.values()[i].getValue());
			entrys[0].add(fileEntrys[i]);
		}
		return bar;
	}
	
	public void setWindowState(int i){
		PREFS.putInt("windowState", windowState);
	}
	
	
	public void show(){
		frame.setVisible(true);
	}
	
	public int getWindowState()			{return PREFS.getInt("windowState", JFrame.NORMAL);}
}

besonders diesen Teil fand ich eigentlich ziemlich angenehm :

Java:
frame.setExtendedState(getWindowState());
if(windowState == JFrame.NORMAL) {
	frame.pack();
	frame.setLocationRelativeTo(null);
}

das getWindowState(); hier direkt das PreferencesObjekt ausließt ;)

letztendlich geht es mir eigentlich nur darum wie ich das am geschicktesten angehe, beim windowState habe ich es schon mit preferences umgesetzt, ( Sinnvoll ? oder doch lieber Properties ?..ich find das so eigentlich ganz angenehm, da Properties mir ja nur Strings liefert, und hier das parsen quasi magic ist :) )

nun frage ich mich , da z.B eine voll Initialisierte JmenuBar mit Actions usw usw, ja unheimlich viel platz wegnimmt, ich es dort so ähnlich machen soll, sprich in lege einfach einen pfad etc. in den preferences / oder einem Properites Objekt an welches dann den Pfad zu einer z.B .xml datei hält und ich dann das menu aus dieser datei parse, oder so ähnlich. Oder vielleicht doch einfach in eine eigene Klasse auslagern ?

Die andere frage ist , erstelle ich am einfachsten einfach ein Preferences Objekt für jeden Bestandteil der Applikation über den ich über die Programmlaufzeit hinaus Daten sichern will oder realisiere ich das dann doch lieber über eine Serialisierte Datei oder so die ich einfach bei jedem Programmstart einlese ?

Zum anderen Halte ich so daten wie z.B Default Werte als Felder oder doch einfach über ein jeweiliges Preferences Objekt ? ^^
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
66 Hits, und keiner der mir sagen kann was die best Practice ist zum händeln von JMenuBars ? und ob ich lieber für jede Komponente eine eigene Propertie Datei nehmen oder direkt ein Preferences Objekt verwenden soll ?
Kommt schon ^^
 

kaoZ

Top Contributor
:lol: find ich ehrlich gesagt auch echt am angenehmsten , muss mich nicht ums parsing kümmen usw. usw.

nun noch die Frage für jede Komponente ein Preferences Objekt welches Lokal statisch gehalten wird oder im Controller alle einlesen und dann im Konstruktor übergeben , oder vielleicht alle werte nur aus einem Preferences Objekt laden und dann im Controller mit den daten alle Komponenten Initialisieren ? ;)
 

kaoZ

Top Contributor
Oder sollte ich ein zentrales Preferences Objekt definieren und im Controller die Werte schreiben, und in den einzelnen Komponenten dann nurnoch auslesen ?
 

taro

Bekanntes Mitglied
Nachdem ich nun wieder eine Bildungslücke schließen konnte - Preferences war mir bisher unbekannt, oute ich mich trotzdem (und auch weiterhin) als Properties-Nutzer:

1. Ist wesentlich angenehmer, wenn Dinge auf mehreren Rechnern geändert werden müssen - einfach Datei(en) verteilen und gut ist
2. mit storeToXML() und loadFromXML() auch vom Handling recht angenehm
3. Ich mag die Registry nicht
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Werd ich mir mal anschauen , danke :)

ich such aber nun erstmal eine möglichkeit, beim schließen die Preferences zu sichern, vermutlich muss ich das FrameEvent irgendwie abfangen, oder einen eigenen listener für den Frame definieren, ich schau mal was man da so machen kann. ;)

Tipps nehmen ich natürlich trotzdem dankend entgegen :D

Ich tüftel grad etwas und hatte zumindest vor es dann alles über den Controller laufen zu lassen, was denke ich auch sinn macht,

dazu habe ich 2 neue Methoden definiert und die GUI und ContentPane Klassen etwas umgeschrieben.

Ich würde dann nurnoch ein Zentrales Preferences Objekt nutzen welches alle Informationen hält, allerdings muss ich mich nun auch erstmal darum kümmern das beim Schließen des Fensters die savePreferences Methode des Controllers aufgerufen wird, aber ich arbeite daran ^^

Java:
public class ApplicationController{
	
	static Preferences PREFS = Preferences.userNodeForPackage(ApplicationController.class);
	
	private ContentPane pane;
	private Gui gui;
	
	public ApplicationController(){
		init();
		loadPreferences();
	}
	
	private void init(){
		pane = new ContentPane();
		gui = new Gui(pane);
	}
	
	private void loadPreferences(){
		gui.setFrameState(PREFS.getInt("frameState", JFrame.NORMAL));
	}
	
	public void savePreferences(){
		PREFS.putInt("frameState", gui.getFrameState());
	}
	
	public void startApplication(){
		gui.show();
	}
	
	public Gui getGui()						{return gui;}
	public ContentPane getContentPane()		{return pane;}
	
	public static void main(String[] args){
		ApplicationController controller = new ApplicationController();
		controller.startApplication();
	}
}
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Ok das war einfacher als ich dachte ^^

die Methode ( unvollständig ) :
Java:
public void savePreferences(){
	PREFS.putInt("frameState", gui.getFrameState());
}

und der Listener ( ebenfalls unvollständig ) aber funktionsfähig beim Schließen werden die Preferences in die Registry geschrieben

Java:
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import editor.ApplicationController;


public class GuiListener implements WindowListener{

	private ApplicationController controller;
	
	public GuiListener(ApplicationController controller){
		this.controller = controller;
	}
	
	@Override
	public void windowOpened(WindowEvent e){}

	@Override
	public void windowClosing(WindowEvent e){}

	@Override
	public void windowClosed(WindowEvent e){
		controller.savePreferences();
	}

	@Override
	public void windowIconified(WindowEvent e){}

	@Override
	public void windowDeiconified(WindowEvent e){}

	@Override
	public void windowActivated(WindowEvent e){}

	@Override
	public void windowDeactivated(WindowEvent e){}
}

:toll::toll::toll:
 

kaoZ

Top Contributor
Kleine Frage turtle,

löse ich solche probleme am besten per delegation ? ich meine normalerweise sollte ja nur die Klasse selbst einfluss auf ihre attribute haben und deren zustände ändern, demnach müsste ich ja das setzen der hier z.B windowListeners ja im Controller einfach an die Gui delegieren, anstatt mir den Frame geben zu lassen und dies auf indirektem weg zu realisieren :

Java:
import java.util.prefs.Preferences;
import javax.swing.JFrame;
import editor.gui.WorkBench;
import editor.gui.GuiListener;
import editor.gui.Gui;


public class ApplicationController{
	
	static Preferences PREFS = Preferences.userNodeForPackage(ApplicationController.class);
	
	private WorkBench workBench;
	private Gui gui;
	
	public ApplicationController(){
		init();
		setListener();
	}
	
	private void init(){
		workBench = new WorkBench();
		gui = new Gui();
	}
	
	private void setListener(){
		gui.setWindowListener(new GuiListener(this));  // <<<----
	}
	
	public void loadPreferences(){
		gui.setFrameState(PREFS.getInt("frameState", JFrame.NORMAL));
	}
	
	public void savePreferences(){
		PREFS.putInt("frameState", gui.getFrameState());
	}
	
	public void startApplication(){
		gui.show();
	}
	
	public Gui getGui()						{return gui;}
	public WorkBench getContentPane()		{return workBench;}
}

Java:
public class Gui{

	private final static String APPLICATION_TITLE = "Rechnungs Editor v1.0";
	
	private JFrame frame;
	private WorkBench workBench;
	
	public Gui(){
		initWorkBench();
		initFrame();
	}
	
	private void initWorkBench(){
		workBench = new WorkBench();
	}
	
	private void initFrame(){
		frame = new JFrame(APPLICATION_TITLE);
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.setContentPane(workBench);
		frame.setExtendedState(getFrameState());
		if(frame.getExtendedState() == JFrame.NORMAL) {
			frame.pack();
			frame.setLocationRelativeTo(null);
		}
	}
	
	public void setWindowListener(WindowListener listener){    // <<<---
		frame.addWindowListener(listener);
	}
	
	public void setFrameState(int state){
		frame.setExtendedState(state);
		frame.revalidate();
	}
	
	public void show(){
		frame.setVisible(true);
	}

	public JFrame getFrame()				{return frame;}
	public int getFrameState()				{return frame.getExtendedState();}
}


und vorallem , gebe ich meinen Komponenten ( GUI und Workbench ) eine Referenz auf den Controller oder nicht ?
 
Zuletzt bearbeitet:

turtle

Top Contributor
In der Tat würde ich es so tun. Ich bin kein Fan davon sich sklavisch an MVC-Paradigmen zu halten.


  1. public void savePreferences(){
  2. PREFS.putInt("frameState", gui.getFrameState());
  3. }


Ich glaube, das es hier kaum besseren/lebbareren Code geben kann, als an ein anderes Objekt zu delegieren und dort putInt aufzurufen, also beispielsweise MainController:savePreferences und wie der MainController an das PREFS-Objekt kommt, per Konstruktor oder als Parameter beim savePreferences() ist mir eigentlich egal. So ist der Code, sich um die Main-Preferences zu kümmern an der "richtigen" Stelle und wird korrekt benutzt/eingebunden um geladen/gespeichert zu werden.
 

kaoZ

Top Contributor
ist jetzt noch die Frage, im moment übergebe ich dem GuiListener einfach eine Referenz auf den Controller

(Der GuiLisetener wird im Controller gesetzt )
Der Controller hält hier je eine Referenz auf die Gui und auf die WorkBench welche dann als contentPane in der Gui fungiert) <-- vielleicht mach ich es mir auch zu kompliziert ?!


Java:
	private void setListener(){
		gui.setWindowListener(new GuiListener(this));
	}

Der GuiListener ist hier aber als Separate Klasse definiert, was mir nun zu denken gibt ist das du public void Fett markiert hattest ^^

würdest du das anders lösen ?

GGf. den listener als innere Klasse , falls ja ,
ich wollte das der ApplicationController der Zentrale "Zugriffspunkt" der Anwendung ist, und dort die komplette initialisierung der Anwendung stattfindet.

Also müsste ich ja wenn auch alle Listener in dieser Klasse als innere Klassen definieren oder nicht ?

Andere Frage wäre wiederrum ob es hier nicht tatsächlich einfacher ist die Gui von JFrame abzuleiten anstatt eine Referenz zu halten , so müsste ich nicht alle Methoden die ich aus der Klasse JFrame benötige nicht in der Klasse Gui auch definieren um dann nicht verkettung von Punktoperatoren und getter an den Frame zu kommen

sprich

Java:
gui.getFrame().addWindowListener(...);

vs.

(durch Vererbung / oder halt bereitstellung einer Methode die dann an den als Attribut gehaltenen Frame delegiert.)

bei Vererbung
Java:
gui.addWindowListener(...);

Delegation in der Klasse gui
Java:
public void addWindowListener(WindowListener l){
   frame.addWindowListener(l);
}

was ist hier die "sinnvollste" option ?

letzteres resultiert ja in mehreren erstellten Methoden die lediglich der delegation dienen damit ich nicht indirekt die Zustände der Attribute ändere ( wie im ersten Beispiel über den Getter)

________________________

Die WorkBench selbst wollte ich so gestalten das ich später über definierte Actions einfach Speziellen Content welche durch JPanel definiert werden hinzufügen kann ( zum Center Bereich, die anderen Bereich enthalten später ToolBars usw. ) , sprich z.B zum bearbeiten von Kundendaten , Rechnungen usw.

Java:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class WorkBench extends JPanel{

	public final static int DEFAULT_WIDTH	 = 800;
	public final static int DEFAULT_HEIGHT	 = 600;
	
	public WorkBench(){
		init();
		initComponents();
		addComponents();
	}
	
	private void init(){
		setPreferredSize(new Dimension(DEFAULT_WIDTH,DEFAULT_HEIGHT));
		setBorder(BorderFactory.createEtchedBorder());
		setLayout(new BorderLayout());
	}
	
	private void initComponents(){
	}
	
	private void addComponents(){
	}
	
	public void setContent(JPanel content){
		add(BorderLayout.CENTER, content);
		revalidate();
	}
}
 
Zuletzt bearbeitet:

turtle

Top Contributor
Mit dem fett markierten Text hast du zu viel rein interpretiert... das war "nur" das Forum welches ein Paste so konvertiert hat.

Also ich glaube, das wir hier zu viel über die richtige Umsetzung von MVC nachdenken und wie ich schon sagte, sehe ich das nicht so eng.

Ich habe mal ein kleines Beispiel zusammengebastelt.
Dieses demonstriert wie sich gemerkt wird, wo und wie gross das JFrame geöffnet war und nimmt dies beim nächsten Start wieder her. Das finde ich recht hilfreich weil es sich merkt, wie gross die GUI der Benutzer gerne hätte.

Weiterhin habe ich als Beispiel ein KundenObjekt aufgenommen. Hier meine ich, solltest du unterscheiden zwischen deinem "Business"-Objekt und der GUI. Die GUI besteht "nur" aus einem JButton. Über den ApplicationController wird auch hier loadPreferences/savePreferences aufegrufen, was aber hier nichts macht. Als Action wird "nur" eine JOptionPane angezeigt.
Java:
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.prefs.Preferences;


import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class ApplicationController {


	static Preferences PREFS = Preferences.userNodeForPackage(ApplicationController.class);
	private JFrame gui;
	private KundenObjekt kundenObjekt;


	ApplicationController(JFrame gui, KundenObjekt kundenObjekt) {
		this.gui = gui;
		this.kundenObjekt = kundenObjekt;
		loadPreferences();
		initComponents();
	}


	private void initComponents() {
		gui.addWindowListener(new WindowListener() {


			@Override
			public void windowOpened(WindowEvent e) {
			}


			@Override
			public void windowIconified(WindowEvent e) {
			}


			@Override
			public void windowDeiconified(WindowEvent e) {
			}


			@Override
			public void windowDeactivated(WindowEvent e) {
			}


			@Override
			public void windowClosing(WindowEvent e) {
				savePreferences();
			}


			@Override
			public void windowClosed(WindowEvent e) {
				savePreferences();
			}


			@Override
			public void windowActivated(WindowEvent e) {
			}
		});
	}


	public void loadPreferences() {
		gui.setExtendedState(PREFS.getInt("frameState", JFrame.NORMAL));
		int x = PREFS.getInt("x", 0);
		int y = PREFS.getInt("y", 0);
		int width = PREFS.getInt("w", 300);
		int height = PREFS.getInt("h", 300);
		gui.setBounds(new Rectangle(new Rectangle(x, y, width, height)));
		// weitere Settings laden
		kundenObjekt.loadPreferences();
	}


	public void savePreferences() {
		PREFS.putInt("frameState", gui.getExtendedState());
		PREFS.putInt("x", gui.getX());
		PREFS.putInt("y", gui.getY());
		PREFS.putInt("w", gui.getWidth());
		PREFS.putInt("h", gui.getHeight());
		// weitere Settings speichern
		kundenObjekt.savePreferences();
	}


	public static void main(String[] args) {
		JFrame frame = new JFrame("turtle");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		KundenObjekt kundenObjekt = new KundenObjekt();
		ApplicationController applicationController = new ApplicationController(frame, kundenObjekt);
		frame.add(kundenObjekt.getPanel());
		frame.setVisible(true);
	}


}


class KundenAction extends AbstractAction {
	private Component parent;


	public KundenAction(Component parent) {
		this.parent = parent;
		putValue(NAME, "Turtle");
	}


	@Override
	public void actionPerformed(ActionEvent e) {
		JOptionPane.showMessageDialog(parent, "Turtle geklickt");
	}


}


class KundenObjekt {
	private JButton btnTurtle;


	public void loadPreferences() {
		System.out.println("KundenObjekt:loadPreferences");
	}


	public JButton getBtnTurtle() {
		return btnTurtle;
	}


	public JPanel getPanel() {
		JPanel kundenPanel = new JPanel();
		btnTurtle = new JButton("turtle-Button");
		KundenAction action = new KundenAction(kundenPanel);
		btnTurtle.setAction(action);
		kundenPanel.add(btnTurtle);
		return kundenPanel;
	}


	public void savePreferences() {
		System.out.println("KundenObjekt:savePreferences");
	}
}
 

kaoZ

Top Contributor
Ich schau mir das in ruhe mal an und überdenke mal das design ^^

aber...


ist das hier schlechter stil ? und sollte man doch lieber alle elemente einzeln hinzufügen ?

Java:
	private void addItems(){
		
//		FileMenu
		
		JMenu fileSubMenu	 = new JMenu(FileMenu.NEW.value());
		JMenuItem invoice	 = new JMenuItem(FileMenu.INVOICE.value());
		JMenuItem estimate	 = new JMenuItem(FileMenu.ESTIMATE.value());
		addMenuItems(fileSubMenu, invoice, estimate);
		
		JMenuItem open		 = new JMenuItem(FileMenu.OPEN.value());
		JMenuItem close		 = new JMenuItem(FileMenu.CLOSE.value());
		JMenuItem importData = new JMenuItem(FileMenu.IMPORT.value());
		JMenuItem exportData = new JMenuItem(FileMenu.EXPORT.value());
		JMenuItem exit		 = new JMenuItem(FileMenu.EXIT.value());
		addMenuItems(fileMenu, fileSubMenu, new JSeparator(), open, close, new JSeparator());
		addMenuItems(fileMenu, importData, exportData, new JSeparator(), exit);
		
		
//		EditMenu
		
	}
	
	private void addMenuItems(JMenu menu, JComponent...components){
		for (JComponent component : components) {
			menu.add(component);
		}
	}

Die MenuBar habe ich hierzu in eine Separate Klasse ausgelagert, um den Gui Code möglichst kurz und knackig zu halten.

ich empfinde das so eigentlich recht angenehm ( über die private Hilftsmethode welche allerdings JComponents als parameter entgegen nimmt, und genau da liegt der Knackpunkt), und es spart mir einen Haufen Code , die Frage ist nun , kann man das später in 'professionellerer..... ;P' Software ruhig so schreiben oder sollten doch wirklich alle Elemente einzeln initialisieren ?

Die Enums werden später noch durch eigenständige Actions ersetzt, welche dann das Enumelement im Konstruktor übergeben bekommen.

Das hier wäre die Komplete JMenuBar ohne die jeweiligen Actions :

Java:
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import editor.enums.ClientMenu;
import editor.enums.EditMenu;
import editor.enums.FileMenu;
import editor.enums.HelpMenu;
import editor.enums.MenuEntry;
import editor.enums.OptionMenu;

@SuppressWarnings("serial")
public class EditorMenuBar extends JMenuBar{
	
	private JMenu fileMenu;
	private JMenu editMenu;
	private JMenu optionMenu;
	private JMenu clientMenu;
	private JMenu helpMenu;
	
	public EditorMenuBar(){
		init();
		addItems();
		addToBar();
	}
	
	private void init(){
		fileMenu	 = new JMenu(MenuEntry.FILE.value());
		editMenu	 = new JMenu(MenuEntry.EDIT.value());
		optionMenu	 = new JMenu(MenuEntry.OPTIONS.value());
		clientMenu	 = new JMenu(MenuEntry.CLIENTS.value());
		helpMenu	 = new JMenu(MenuEntry.HELP.value());
	}
	
	private void addItems(){
		
//		FileMenu
		
		JMenu fileSubMenu	 = new JMenu(FileMenu.NEW.value());
		JMenuItem invoice	 = new JMenuItem(FileMenu.INVOICE.value());
		JMenuItem estimate	 = new JMenuItem(FileMenu.ESTIMATE.value());
		addMenuItems(fileSubMenu, invoice, estimate);
		
		JMenuItem open		 = new JMenuItem(FileMenu.OPEN.value());
		JMenuItem close		 = new JMenuItem(FileMenu.CLOSE.value());
		JMenuItem importData = new JMenuItem(FileMenu.IMPORT.value());
		JMenuItem exportData = new JMenuItem(FileMenu.EXPORT.value());
		JMenuItem exit		 = new JMenuItem(FileMenu.EXIT.value());
		addMenuItems(fileMenu, fileSubMenu, new JSeparator(), open, close, new JSeparator());
		addMenuItems(fileMenu, importData, exportData, new JSeparator(), exit);
		
		
//		EditMenu
		
		JMenuItem cut	 = new JMenuItem(EditMenu.CUT.value());
		JMenuItem copy	 = new JMenuItem(EditMenu.COPY.value());
		JMenuItem paste	 = new JMenuItem(EditMenu.PASTE.value());
		JMenuItem delete = new JMenuItem(EditMenu.DELETE.value());
		JMenuItem search = new JMenuItem(EditMenu.SEARCH.value());
		JMenuItem sort	 = new JMenuItem(EditMenu.SORT.value());
		addMenuItems(editMenu, cut, copy, paste, new JSeparator());
		addMenuItems(editMenu, delete, search, sort);
		
//		OptionMenu
		
		JMenu display	= new JMenu(OptionMenu.DISPLAY.value());
		JMenuItem small = new JMenuItem(OptionMenu.SMALL.value());
		JMenuItem mid 	= new JMenuItem(OptionMenu.MID.value());
		JMenuItem big	= new JMenuItem(OptionMenu.BIG.value());
		JMenuItem full 	= new JMenuItem(OptionMenu.FULL.value());
		addMenuItems(display, small, mid, big, full);
		
		JMenuItem user		 = new JMenuItem(OptionMenu.USER.value());
		JMenuItem options	 = new JMenuItem(OptionMenu.OPTIONS.value());
		addMenuItems(optionMenu, display, new JSeparator(), user, options);

//		ClientMenu
		
		JMenuItem newClient		 = new JMenuItem(ClientMenu.NEW.value());
		JMenuItem editClient	 = new JMenuItem(ClientMenu.EDIT.value());
		JMenuItem copyClient	 = new JMenuItem(ClientMenu.COPY.value());
		JMenuItem searchClient	 = new JMenuItem(ClientMenu.SEARCH.value());
		JMenuItem deleteClient	 = new JMenuItem(ClientMenu.DELETE.value());
		addMenuItems(clientMenu, newClient, editClient, copyClient);
		addMenuItems(clientMenu, new JSeparator(), searchClient, new JSeparator(), deleteClient);
		
//		HelpMenu
		
		JMenuItem shortcuts	 = new JMenuItem(HelpMenu.SHORTCUTS.value());
		JMenuItem about		 = new JMenuItem(HelpMenu.ABOUT.value());
		JMenuItem contact 	 = new JMenuItem(HelpMenu.CONTACT.value());
		JMenuItem docu		 = new JMenuItem(HelpMenu.DOCU.value());
		addMenuItems(helpMenu, shortcuts,new JSeparator(), about, contact, new JSeparator(), docu);
		
	}
	
	private void addMenuItems(JMenu menu, JComponent...components){
		for (JComponent component : components) {
			menu.add(component);
		}
	}
	
	private void addToBar(){
		add(fileMenu);
		add(editMenu);
		add(optionMenu);
		add(clientMenu);
		add(helpMenu);
	}
}
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
Was ich ein wenig unschön finde ist die Tatsache das ich die Referenzen hin und her reichen muss , für den oberen Teil habe ich bereits Actions geschrieben, welchen ich aber immer die zu steuernde Componente als Referenz übergeben muss, somit hält auch die Action jeweils eine Referenz auf diese Componente,

gibt es da schöne Lösungsansätze ?

Java:
import java.awt.event.KeyEvent;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import editor.actions.CloseAction;
import editor.actions.EstimateAction;
import editor.actions.ExitAction;
import editor.actions.ExportAction;
import editor.actions.ImportAction;
import editor.actions.InvoiceAction;
import editor.actions.OpenAction;
import editor.enums.ClientMenu;
import editor.enums.EditMenu;
import editor.enums.FileMenu;
import editor.enums.HelpMenu;
import editor.enums.MenuEntry;
import editor.enums.OptionMenu;

@SuppressWarnings("serial")
public class EditorMenuBar extends JMenuBar{
	
	private Gui gui;
	
	private JMenu fileMenu;
	private JMenu editMenu;
	private JMenu optionMenu;
	private JMenu clientMenu;
	private JMenu helpMenu;
	
	public EditorMenuBar(Gui gui){
		this.gui = gui;
		init();
		addItems();
		addToBar();
	}
	
	private void init(){
		fileMenu = new JMenu(MenuEntry.FILE.value());
		fileMenu.setMnemonic(KeyEvent.VK_D);
		
		editMenu = new JMenu(MenuEntry.EDIT.value());
		editMenu.setMnemonic(KeyEvent.VK_B);
		
		optionMenu = new JMenu(MenuEntry.OPTIONS.value());
		optionMenu.setMnemonic(KeyEvent.VK_E);
		
		clientMenu = new JMenu(MenuEntry.CLIENTS.value());
		clientMenu.setMnemonic(KeyEvent.VK_K);
		
		helpMenu = new JMenu(MenuEntry.HELP.value());
		helpMenu.setMnemonic(KeyEvent.VK_H);
	}
	
	private void addItems(){
		
//		FileMenu
		
		JMenu fileSubMenu	 = new JMenu(FileMenu.NEW.value());
		JMenuItem invoice	 = new JMenuItem(new InvoiceAction(gui.getWorkBench()));
		JMenuItem estimate	 = new JMenuItem(new EstimateAction(gui.getWorkBench()));
		addMenuItems(fileSubMenu, invoice, estimate);
		
		JMenuItem open		 = new JMenuItem(new OpenAction(gui.getFrame()));
		JMenuItem close		 = new JMenuItem(new CloseAction());
		JMenuItem importData = new JMenuItem(new ImportAction());
		JMenuItem exportData = new JMenuItem(new ExportAction());
		JMenuItem exit		 = new JMenuItem(new ExitAction(gui.getFrame()));
		addMenuItems(fileMenu, fileSubMenu, new JSeparator(), open, close, new JSeparator());
		addMenuItems(fileMenu, importData, exportData, new JSeparator(), exit);
		
		
//		EditMenu
		
		JMenuItem cut	 = new JMenuItem(EditMenu.CUT.value());
		JMenuItem copy	 = new JMenuItem(EditMenu.COPY.value());
		JMenuItem paste	 = new JMenuItem(EditMenu.PASTE.value());
		JMenuItem delete = new JMenuItem(EditMenu.DELETE.value());
		JMenuItem search = new JMenuItem(EditMenu.SEARCH.value());
		JMenuItem sort	 = new JMenuItem(EditMenu.SORT.value());
		addMenuItems(editMenu, cut, copy, paste, new JSeparator());
		addMenuItems(editMenu, delete, search, sort);
		
//		OptionMenu
		
		JMenu display	= new JMenu(OptionMenu.DISPLAY.value());
		JMenuItem small = new JMenuItem(OptionMenu.SMALL.value());
		JMenuItem mid 	= new JMenuItem(OptionMenu.MID.value());
		JMenuItem big	= new JMenuItem(OptionMenu.BIG.value());
		JMenuItem full 	= new JMenuItem(OptionMenu.FULL.value());
		addMenuItems(display, small, mid, big, full);
		
		JMenuItem user		 = new JMenuItem(OptionMenu.USER.value());
		JMenuItem options	 = new JMenuItem(OptionMenu.OPTIONS.value());
		addMenuItems(optionMenu, display, new JSeparator(), user, options);

//		ClientMenu
		
		JMenuItem newClient		 = new JMenuItem(ClientMenu.NEW.value());
		JMenuItem editClient	 = new JMenuItem(ClientMenu.EDIT.value());
		JMenuItem copyClient	 = new JMenuItem(ClientMenu.COPY.value());
		JMenuItem searchClient	 = new JMenuItem(ClientMenu.SEARCH.value());
		JMenuItem deleteClient	 = new JMenuItem(ClientMenu.DELETE.value());
		addMenuItems(clientMenu, newClient, editClient, copyClient);
		addMenuItems(clientMenu, new JSeparator(), searchClient, new JSeparator(), deleteClient);
		
//		HelpMenu
		
		JMenuItem shortcuts	 = new JMenuItem(HelpMenu.SHORTCUTS.value());
		JMenuItem about		 = new JMenuItem(HelpMenu.ABOUT.value());
		JMenuItem contact 	 = new JMenuItem(HelpMenu.CONTACT.value());
		JMenuItem docu		 = new JMenuItem(HelpMenu.DOCU.value());
		addMenuItems(helpMenu, shortcuts,new JSeparator(), about, contact, new JSeparator(), docu);
	}
	
	private void addMenuItems(JMenu menu, JComponent...components){
		for (JComponent component : components) {
			menu.add(component);
		}
	}
	
	private void addToBar(){
		add(fileMenu);
		add(editMenu);
		add(optionMenu);
		add(clientMenu);
		add(helpMenu);
	}
}

Das hier wäre z.B eine dazugehörende Action

Java:
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import editor.enums.FileMenu;
import editor.gui.WorkBench;
import editor.gui.components.Invoice;


@SuppressWarnings("serial")
public class InvoiceAction extends AbstractAction{

	private WorkBench workBench;
	
	public InvoiceAction(WorkBench workBench){
		super(FileMenu.INVOICE.value());
		this.workBench = workBench;
	}
	
	@Override
	public void actionPerformed(ActionEvent e){
		workBench.setContent(new Invoice());
	}
}

Invoice repräsentiert hier (später) eine Rechnung in Form eines JPanels

der Panel wird über die setContent() Methode der WorkBench gesetzt :

Java:
	public void setContent(JPanel content){
		removeAll();
		add(BorderLayout.CENTER, content);
		revalidate();
	}

jetzt mal unabhängig vom observer pattern , wie ließe sich das eleganter lösen , oder ist die Funktionsweise , der Lösungsansatz soweit in Ordnung, ist wie gesagt mein erstes Größeres Projekt, die Anzahl der Klassen beläuft sich bis jetzt^^ auf ca 50, ich versuche hier auch es so Atomar wie möglich zu halten.
 
Zuletzt bearbeitet:

kaoZ

Top Contributor
EDIT : ^^

Ich reiche nun lediglich noch eine Referenz auf die Gui an die Komponenten weiter, die Gui selbst bietet nun mehrere Methoden an die dann an die Entsprechende Komponenten delegieren, dies schaut recht gut aus, und funktioniert :)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
C JMenuBar AWT, Swing, JavaFX & SWT 6
K Event Handling Über JMenuBar die diversen Panels anzeigen AWT, Swing, JavaFX & SWT 10
J Swing JMenuItem blockiert JMenuBar AWT, Swing, JavaFX & SWT 2
S JMenuBar bei sichtbarer JGlassPane AWT, Swing, JavaFX & SWT 1
R JMenuBar.setFont tut nix ? AWT, Swing, JavaFX & SWT 1
I Swing JMenuBar auch unten am JFrame? AWT, Swing, JavaFX & SWT 2
A Swing JMenuBar updaten AWT, Swing, JavaFX & SWT 2
Q Designfrage zur JMenuBar AWT, Swing, JavaFX & SWT 6
S JMenuBar wiederverwenden und Eventhandling anpassen AWT, Swing, JavaFX & SWT 4
B Swing JMenuBar unten in der Frame setzen? AWT, Swing, JavaFX & SWT 15
Q Fragen zur JMenuBar & Co. AWT, Swing, JavaFX & SWT 3
M Über eine JMenuBar überprüfen ob ein JCheckBoxMenuItem selectiert ist. AWT, Swing, JavaFX & SWT 4
M JMenuBar, JMenu, JMenuItem wird nicht angezeigt AWT, Swing, JavaFX & SWT 16
G Swing JMenuBar zu weit links und oben dargestellt AWT, Swing, JavaFX & SWT 5
B Swing Dynamische JMenuBar AWT, Swing, JavaFX & SWT 2
J JMenuBar ist geaddet, aber nicht im Frame. Wo ist der Fehler? (inkl. Code) AWT, Swing, JavaFX & SWT 2
D JMenuBar - CardLayout (Klasse anzeigen) AWT, Swing, JavaFX & SWT 3
S JMenuBar Frame Abstand AWT, Swing, JavaFX & SWT 3
H jMenuBar AWT, Swing, JavaFX & SWT 13
NR_EIGHT Swing Probleme mit JMenuBar AWT, Swing, JavaFX & SWT 6
M JMenuBar im Applet und paint AWT, Swing, JavaFX & SWT 9
Madlip JMenuBar in JFrame AWT, Swing, JavaFX & SWT 5
B JFrame / JMenuBar => Anfängerprobleme AWT, Swing, JavaFX & SWT 2
R JMenuBar AWT, Swing, JavaFX & SWT 2
S JMenuBar nach 1. Klick deselectieren AWT, Swing, JavaFX & SWT 6
Z JMenuBar wird nicht in JFrame angezeigt AWT, Swing, JavaFX & SWT 2
N JMenuBar verschwindet nicht nach ComponentEvent AWT, Swing, JavaFX & SWT 6
C JMenuBar aktualisieren? AWT, Swing, JavaFX & SWT 2
A Doppelte JMenuBar AWT, Swing, JavaFX & SWT 2
X NullPointerException beim Einfügen einer JMenuBar AWT, Swing, JavaFX & SWT 4
C JMenuBar im JFrame abgehackt AWT, Swing, JavaFX & SWT 7
J Swing JFrame mit JMenuBar, allerdings ohne Erfolg AWT, Swing, JavaFX & SWT 10
K Look&Feel von JMenuBar und Subkomponenten anpassen AWT, Swing, JavaFX & SWT 6
C JMenuBar linksbündig AWT, Swing, JavaFX & SWT 6
C Größe JMenuBar AWT, Swing, JavaFX & SWT 5
KrokoDiehl Swing Actions direkt auf der JMenuBar AWT, Swing, JavaFX & SWT 6
L Swing Kommunikation zwischen JMenuBar und anderen Componenten AWT, Swing, JavaFX & SWT 2
Developer_X Swing JMenuBar Layout AWT, Swing, JavaFX & SWT 2
kniffel JMenuBar aus anderer Klasse AWT, Swing, JavaFX & SWT 10
G Dynamische JMenuBar AWT, Swing, JavaFX & SWT 2
G JMenuBar verschmälern AWT, Swing, JavaFX & SWT 2
M ALT shortcut für JMenuBar deaktivieren AWT, Swing, JavaFX & SWT 3
X JMenuBar überlappt von JPanel :( AWT, Swing, JavaFX & SWT 7
M4nuel Warum überlagert JDesktopPane mein JMenuBar? AWT, Swing, JavaFX & SWT 5
G StatusBar Optik wie JMenuBar; GUI-Erzeugung delegieren AWT, Swing, JavaFX & SWT 2
J JMenuBar in Frame einbauen AWT, Swing, JavaFX & SWT 6
D Canvas über JMenuBar AWT, Swing, JavaFX & SWT 7
P JMenuBar und JToolBar Anzeige Probleme AWT, Swing, JavaFX & SWT 5
C JLabel in JMenuBar frei platzieren AWT, Swing, JavaFX & SWT 2
B JMenubar AWT, Swing, JavaFX & SWT 5
Chris_1980 Makierungsfarbe bei JMenuBar ändern AWT, Swing, JavaFX & SWT 5
L Problem mit JMenuBar AWT, Swing, JavaFX & SWT 5
F JTextField rechts in der JMenuBar AWT, Swing, JavaFX & SWT 4
A gezeichnete Linie verschwindet, wenn ich JMenuBar öffne AWT, Swing, JavaFX & SWT 2
I JMenuBar - Menüs sortieren AWT, Swing, JavaFX & SWT 2
S JMenuBar mit Action belegen! AWT, Swing, JavaFX & SWT 5
M JMenuBar AWT, Swing, JavaFX & SWT 7
B JMenuBar sowie Buttons nach repaint auf JPanel AWT, Swing, JavaFX & SWT 2
T JMenuBar ausblenden lassen aber Hotkeys sollen erhalten sein AWT, Swing, JavaFX & SWT 2
S JMenuBar + update AWT, Swing, JavaFX & SWT 3
M JMenuBar - JMenu mit Tastenkombination aufrufen / anzeigen AWT, Swing, JavaFX & SWT 8
T JMenuBar zweizeilig AWT, Swing, JavaFX & SWT 2
A JMenuBar + paint (Image) AWT, Swing, JavaFX & SWT 6
M JmenuBar wird net angezeigt :( AWT, Swing, JavaFX & SWT 6
U komplette JMenuBar deaktivieren? AWT, Swing, JavaFX & SWT 4
S Mausklick reagiert nicht im JMenuBar AWT, Swing, JavaFX & SWT 4
A JMenuBar verschieben. AWT, Swing, JavaFX & SWT 4
T JMenuBar wird nicht richtig angezeigt AWT, Swing, JavaFX & SWT 5
H JFrame, JMenuBar, ScrollBar AWT, Swing, JavaFX & SWT 3
J Swing GUI-Einstellungen mittels Preferences AWT, Swing, JavaFX & SWT 2
0 Ist "sequence.fallback" aus den font.properties zur Laufzeit änderbar AWT, Swing, JavaFX & SWT 0
MiMa Properties AWT, Swing, JavaFX & SWT 1
G Properties automatisch laden AWT, Swing, JavaFX & SWT 10
T JavaFX Allgemeine Fragen zu JavaFX (uA zu Properties) AWT, Swing, JavaFX & SWT 6
F JavaFX Properties und NULL Werte AWT, Swing, JavaFX & SWT 2
R Einbinden von Properties für Swing (Beschriftungen etc.) AWT, Swing, JavaFX & SWT 2
loadbrain Probleme mit Properties load AWT, Swing, JavaFX & SWT 5
F Settings (bzw. Properties) über GUI ändern? AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen

Neue Themen


Oben