Fragen zum allgemeinen Code-Design bei GUIs

Hallo!

Ich habe bemerkt, dass ich Probleme beim allgemeinen Code-Design bei GUIs habe.
Nun zu meinen Fragen.

Früher ist meine GUI von FIDER in fast nur einer einzigen Klasse gewesen, und der ganze GUI-Code in einer Methode…
Nachdem ich dann irgendwann die Übersicht verloren habe und ich es mit erweitern der GUI fast vergessen konnte, habe ich dann mal den GUI-Code auf mehrere Klassen verteilt.

Zur Verwaltung habe ich dann die Klasse GUIManager gebastelt, die mir Zugriff auf alle wichtigen GUI-Elemente wie Frame und Panels gibt. Das Fenster des Programms ist in einer Klasse, die von JFrame erbt. In ihr werden auch andere Instanzen von JPanel-Klassen erzeugt. Auf den Frame und die ganzen Panels habe ich alle mit dem GUIManager Zugriff, auch wenn diese eigentlich in meiner Frame-Klasse abgespeichert sind.
1. Frage: Ist das so richtig? Ist es auch so üblich, dass man dann über diesen „Manager“ Zugriff auf alle meist verwendeten Panels hat? Ist es dann auch sinnvoll, Methoden in z. B. der Frame-Klasse anzubieten, mit denen man auf die in der Frame-Klasse erzeugten Panels hat?

Jetzt kommt das Problem, wie denn der Frame und die ganzen Panels Zugriff auf den GUIManager bekommen. Bis jetzt habe ich immer eine Instanz über den Konstruktor mitgegeben, was allerdings sehr mühsam ist.
2. Frage: Wäre es besser, wenn GUIManager einen privaten Konstruktor hat und eine statische Methode getInstance() oder so?

3. Frage: Wenn jetzt jede Klasse eine Referenz auf den GUIManager bekommen kann, ist es dann nach „gutem“ Code-Design erlaubt, die Referenz in einer privaten Instanzvariablen abzuspeichern und ist es dann sinnvoll, eine private Methode getGUIManager() zu machen, um einfach Code zu „sparen“?

Das war’s erstmal, was mir auf den ersten „Denker“ einfällt :wink:

Gruß,
pcworld

Das klingt eigentlich ganz gut, bei mir ist das etwas anders.
Jede Klasse kennt eigentlich nur sich selbst und einen Controller, der ist ein Singleton (wie deine Frage 2)
Nur die Dialoge/Frames kennen einige ihrer Panels die sie enthalten.
Einige wichtige Elemente werden dem Controller auch bekannt gegeben aber er kennt niemals alle.

Danke erstmal!
Dieser Controller, den du hast, erzeugt der auch den Frame? Oder geschieht das in der Main-Klasse?

Kennen auch die Panels, die die Frames usw. enthalten, auch ihr Elternelement (also z. B. den Frame)? Oder holen sie sich dann die Objekte, die sie brauchen, über den Controller?

Wie werden deinem Controller die Elemente bekannt gegeben? Gibt es bei dir Methoden wie setHeaderPanel(Panel p)?
Bei mir ist der „Aufruf-Stack“ ungefähr so, was ich allerdings noch nie so richtig gut fand…:


#**GUIManager**
##lädt die Frame-Klasse
##Jetzt gibt es im GUIManager Methoden wie **getHeaderPanel()**, usw., deren Code dann ungefähr so aussieht (Bsp.):
	public UploadTable getUploadTable() {
		return getFrame().getUploadPanel().getUploadTable();
	}

#**Frame-Klasse**
##lädt die ganzen Panels usw.
##Methoden: z. B. **getHeaderPanel()**, ...

Ich denke, dass kann man geschickter lösen, aber da gibt es sicherlich mehrere Möglichkeiten.

Noch ein Frage, die richtet sich allerdings wohl doch eher an allgemeines „Code-Designing“: Ich vermute mal, die Klassen speichern sich in einer privaten Instanzvariablen eine Referenz auf den Controller (um Code zu sparen ;-)), wenn sie sie über Controller.getInstance() oder so bekommen haben. Machst du dann extra eine private Methode getController() oder so? Oder lässt du den Code direkt auf die Instanzvariable zugreifen? (Also Frage 3 im ersten Post)

Gruß,
pcworld

Nein der Frame erzeugt in der Regel den Controler, wobei das ja auch egal ist da er ein Singleton ist.

Componenten kennen immer ihren Parent (getParent()) aber ich verwende ihn nie bzw. sehr sehr selten. Ich versuche eigentlich immer das alle Elemente möglichst unabhängig von einander sind. Wenn es Abhängigkeiten gibt löse ich das oft mit Listenern.
Jep das wird einfach über Setter gemacht.

Ne bei mir sieht das ungefähr so aus


- Frame erzeugen
-- Menu erzeugen
-- Toolbar erzeugen
-- Panels erzeugen
-- einzelne Elemente im Controller setzen

Ich geb dem Controller nur die Elemente die er für seine Arbeit braucht, z.B. das Menu wenn er Einträge de-/aktivieren soll. In der Regel kennt er nur das Menu und die Toolbar um dort Sachen zu de-/aktivieren und den Hauptframe um ihn als Parent für Fehlermeldungen zu nehmen.

Wieso eine private Methode getController?
Ich hab in den Klassen die den Controller brauchen immer eine statische Variable die den Controller enthält.
private static final Controller controller = Controller.getInstance();

Danke!

Kümmert sich dein Controller nur um die GUI-Elemente, oder auch um sonstige Sachen?
Leiht er auch nur Zugriff auf die Elemente, oder ist es auch der Verwalter der GUI? Oder hast du da was anderes?

Gruß,
pcworld

Der Controller ist für viele (nicht alle) Steuerungen zuständig.
Einige Teile die klein und innerhalb eines Panels sind bleiben dort alles andere geht in den Controller.
Der Controller gibt bei mir niemals Objekte raus, er nimmt nur aufrufe entgegen und führt sie aus bzw. leitet sie weiter.

Wenn ich mal wieder Internet zuhause hab kann ich dir mal ein Beispiel zeigen (theoretisch bekomm ichs heute abend :D)

Wie genau meinst du das?
Naja, ich kann auch auf’s Beispiel warten :wink: (in einer PN von dier hieß es schonmal, du bekommest am 8. Internet :smiley: ;-))

Gruß,
pcworld

Es gibt in meinem Controller keine get Methoden nur ein paar set

Ja gestern kam wieder ein Techniker aber der hat den Anschlusskasten nicht gefunden daher hab ich immer noch kein Internet

Und wie kommen dann ActionListener usw. an andere GUI-Objekte, die sie benötigen?
Was macht der Controller dann mit den per Settern übergebenen Objekten, wenn er ja keine Getter für sie hat?

Gruß,
pcworld

Die kennen keine andere Objekte, wenn es kleine Aktionen sind und nur Objekte des gleichen Panels sind dann greifen sie direkt zu sonst heißt es nur controller.machdas() und der führt dann alles nötige aus.
In der GUI sollte so wenig wie möglich Logik stehen (eigentlich garkeine aber das geht einfach nicht)

Mal so am Rande…

Singleton ist ein Anti-Pattern… das heisst man soll es vermeiden wo es nur geht.

Man sollte eher an Dependency Injection oder aehnliches nutzen (entweder selbst anleihern oder PICO oder Spring oder aehnliches verwenden )

Im Grunde sind Singletons zu weit uber 90% der Faelle zu vermeiden !

Naja darüber lässt sich streiten :wink:
Für ein Objekt Spring aufsetzen ist meiner Meinung nach etwas übertrieben.

[QUOTE=EagleEye]Naja darüber lässt sich streiten :wink:
Für ein Objekt Spring aufsetzen ist meiner Meinung nach etwas übertrieben.[/QUOTE]
zum einen gehts ja nicht um ein Objekt, sondern um ein Projekt… zum anderen muss man natuerlich nicht gleich Spring aufsetzen - Google Guice geht auch :wink: oder eben einfach selbst organisieren…

wollte eben nur anmerken, dass Singletons are evil

Selbst organisieren → Singleton :stuck_out_tongue:
Hier mal der Code von meinem Controller und der als Beispiel von meinem Menu

 * Created on 17.02.2007
 * 
 * Copyright (c) 2007, Kay Czarnotta
 * 
 * All rights reserved.
 */
package de.eagleside.databasedesigner.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.Action;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import de.eagleside.databasedesigner.data.Settings;
import de.eagleside.databasedesigner.data.databaseproject.Project;
import de.eagleside.databasedesigner.event.DesignerChangeEvent;
import de.eagleside.databasedesigner.exception.ProjectIOException;
import de.eagleside.databasedesigner.gui.designer.DesignerPanel;
import de.eagleside.databasedesigner.gui.designer.TablePanel;
import de.eagleside.databasedesigner.gui.dialog.CreateScriptDialog;
import de.eagleside.databasedesigner.gui.dialog.project.ProjectDialog;
import de.eagleside.databasedesigner.gui.dialog.settings.SettingsDialog;
import de.eagleside.databasedesigner.gui.dialog.table.TableDialog;
import de.eagleside.databasedesigner.io.EDBPFileFilter;
import de.eagleside.databasedesigner.io.IOClass;
import de.eagleside.databasedesigner.listener.DesignerListener;
import de.eagleside.databasedesigner.plugins.DatabaseImportDialog;
import de.eagleside.databasedesigner.plugins.PluginLoader;
import de.eagleside.databasedesigner.plugins.interfaces.ProjectImporter;
import de.eagleside.io.Util;
import de.eagleside.io.filefilter.ImageFileFilter;

/**
 * Controller zu Steuerung der Aktionen der Toolbar und des Menüs.
 * 
 * @author Eagle Eye
 * 
 */
public class MainController
{
  private static final Settings settings = Settings.getInstance();
  private static MainController instance = new MainController();
  private DesignerChangeListener changelistener = new DesignerChangeListener();
  private MainFrame mainframe;
  private Toolbar toolbar;
  private MenuBar menu;
  private PluginLoader pluginmanager;
  private DatabaseImportDialog importdialog;

  /**
   * Erzeugen eines neuen Objekts.
   */
  private MainController()
  {}

  /**
   * Gibt die aktuelle Instanz zurück.
   */
  public static MainController getInstance()
  {
    return instance;
  }

  /**
   * Setzen des Hauptfensters.
   */
  public void setMainFrame(MainFrame mainframe)
  {
    if(this.mainframe != null)
      this.mainframe.removeDesignerListener(changelistener);
    this.mainframe = mainframe;
    mainframe.addDesignerListener(changelistener);
    mainframe.addTableActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        showTableDialog(e);
      }

    });
  }

  /**
   * Setzen des Menubars.
   */
  public void setMenuBar(MenuBar menu)
  {
    this.menu = menu;
  }

  /**
   * Setzen des Clickmodes für das Designermainpanel.
   */
  public void setDesignerPanelMouseClickMode(int mode)
  {
    switch(mode)
    {
      case DesignerPanel.MOUSEMODE_NORMAL:
        toolbar.selectNormal();
        break;

      case DesignerPanel.MOUSEMODE_ADD_TABLE:
        toolbar.selectTableAdd();
        break;

      case DesignerPanel.MOUSEMODE_REMOVE_ELEMENT:
        toolbar.selectTableRemove();
        break;
      default:
        break;
    }
    mainframe.setDesignerPanelMouseClickMode(mode);
  }

  /**
   * Setzen der Toolbar.
   */
  public void setToolBar(Toolbar toolbar)
  {
    this.toolbar = toolbar;
    toolbar.selectNormal();
  }

  /**
   * Beenden des Programms.
   */
  public void close()
  {
    mainframe.close();
  }

  /**
   * Erstellen eines neuen Projekts.
   */
  public void newProject()
  {
    if(closeProject())// MARK Anpassen wenn mehrere Projekte möglich sein sollen
    {
      Project p = openProjectDialog(new Project());
      if(p != null)
        mainframe.addProject(p);
    }
  }

  /**
   * Öffnen des Projektdialogs.
   */
  public void openProjectDialog()
  {
    Project p = mainframe.getProject();
    if(p != null)
    {
      p = openProjectDialog(p);
      if(p != null)
        mainframe.addProject(p);
    }
  }

  /**
   * Öffnen eines neuen Projekts.
   */
  public void openProject()
  {
    openProject((File)null);
  }

  /**
   * Öffnen des Projekts aus der übergebenen Datei.
   */
  public void openProject(String f)
  {
    openProject(new File(f));
  }

  /**
   * Öffnen des Projekts aus der übergebenen Datei.
   */
  public void openProject(File f)
  {
    // schließen des aktuellen Projekts
    if(closeProject())// MARK Anpassen wenn mehrere Projekte möglich sein sollen
    {
      /*
       * wenn keine Datei angegeben wurde die geöffnet werden soll wird der Dialog zum Öffnen einer
       * Datei geöffnet.
       */
      if(f == null)
      {
        JFileChooser fc = new JFileChooser(settings.getLastFileChooserPath());
        fc.addChoosableFileFilter(new EDBPFileFilter());
        fc.setMultiSelectionEnabled(false);
        if(fc.showOpenDialog(mainframe) == JFileChooser.APPROVE_OPTION)
        {
          f = fc.getSelectedFile();
        }
        else
          return;
      }

      if(f != null)
      {
        if(!f.exists())
        {
          JOptionPane.showMessageDialog(mainframe, "Die Datei \"" + f.getName() + "\" ist nicht vorhanden!");
          menu.removeProjectHistoryFile(f);
        }
        else
          try
          {
            settings.setLastFileChooserPath(f);
            openProject(IOClass.readProject(f, mainframe));
            mainframe.setSaved();// da geladen wurde muss die noch nicht gespeichert werden
            menu.addProjectHistoryFile(f);
          }
          catch(ProjectIOException ex)
          {
            ex.printStackTrace();
            switch(ex.getType())
            {
              case ProjectIOException.SYNTAX_ERROR:
                JOptionPane.showMessageDialog(mainframe, "Es ist ein Fehler beim Laden des Projekts aufgetreten, die Datei enthält Fehler!");
                break;
              case ProjectIOException.VERSION_NOT_SUPPORTED:
                JOptionPane.showMessageDialog(mainframe, "<html>Die Verion der Projektdatei wird nicht unterstützt,<br />"
                    + "möglicherweise verwende Sie eine alte Version des Programms</html>!");
                break;
              default:
                JOptionPane.showMessageDialog(mainframe, "Unbekannter Fehler beim Laden des Projekts!");
                break;
            }
          }
          catch(Exception ex)
          {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(mainframe, "Unbekannter Fehler beim Laden des Projekts!");
          }
      }
    }
  }

  public void openProject(Project project)
  {
    mainframe.addProject(project);
  }

  public void openUnsavedProject(Project project)
  {
    openProject(project);
    // mainframe.setUnsaved();
  }

  /**
   * Schließen des Projekts.
   */
  public boolean closeProject()
  {
    return mainframe.closeCurrentProject();
  }

  /**
   * Speichern des Projekts.
   */
  public boolean saveProject()
  {
    Project p = mainframe.getProject();
    if(p == null)
      return false;

    boolean ret;
    if(p.getProjectFilePath() != null)
      ret = saveProject(p, p.getProjectFilePath());
    else
      ret = saveProjectAs();

    return ret;
  }

  /**
   * Speichern des Projekts unter einer neuen Datei.
   */
  public boolean saveProjectAs()
  {
    Project p = mainframe.getProject();
    JFileChooser fc = new JFileChooser(settings.getLastFileChooserPath());
    fc.addChoosableFileFilter(new EDBPFileFilter());
    fc.setMultiSelectionEnabled(false);
    if(fc.showSaveDialog(mainframe) == JFileChooser.APPROVE_OPTION)
    {
      return saveProject(p, fc.getSelectedFile().toString());
    }
    return false;
  }

  /**
   * Speichern des Projekts unter der angegebenen Datei.
   */
  private boolean saveProject(Project p, String file)
  {
    try
    {
      if(!file.endsWith(".edbp"))
        file += ".edbp";
      IOClass.writeProject(p, file);
      p.setProjectFilePath(file);
      mainframe.setSaved();
      menu.addProjectHistoryFile(file);
      return true;
    }
    catch(Exception ex)
    {
      ex.printStackTrace();
      JOptionPane.showMessageDialog(mainframe, "Unbekannter Fehler beim Speichern des Projekts");
      return false;
    }
  }

  /**
   * Anzeigen der Einstellungen.
   */
  public void showSettings()
  {
    SettingsDialog sd = new SettingsDialog(mainframe);
    sd.setVisible(true);
  }

  /**
   * Exportieren des aktuellen Projekts als Bild.
   */
  public void exportImage()
  {
    try
    {
      BufferedImage im = mainframe.createImage();

      JFileChooser fc = new JFileChooser(settings.getLastFileChooserPath());
      ImageFileFilter[] ff = Util.getImageIOWriterFileFilter();
      for(ImageFileFilter iff : ff)
        fc.addChoosableFileFilter(iff);
      fc.setAcceptAllFileFilterUsed(false);
      fc.setFileFilter(Util.getPNGFileFilter(ff));

      if(fc.showSaveDialog(mainframe) == JFileChooser.APPROVE_OPTION)
      {
        File f = fc.getSelectedFile();
        settings.setLastFileChooserPath(f);
        String imagetype;
        if(fc.getFileFilter() instanceof ImageFileFilter)
        {
          imagetype = ((ImageFileFilter)fc.getFileFilter()).getImagetype();
          if(!f.getName().toUpperCase().endsWith('.' + imagetype))
            f = new File(f + "." + imagetype.toLowerCase());
        }
        else
        {
          int start = f.getName().indexOf('.');
          if(start == -1)
          {
            JOptionPane.showMessageDialog(mainframe, "Sie haben kein bekanntes Dateiformat gewählt");
            return;
          }
          imagetype = f.getName().substring(start);
          System.out.println(imagetype);
        }
        ImageIO.write(im, imagetype, f);
      }
    }
    catch(Exception ex)
    {
      ex.printStackTrace();
    }
  }

  /**
   * Export des aktuellen Projekts als SQL Skript.
   */
  public void exportScript()
  {
    Project p = mainframe.getProject();
    if(p == null)
      JOptionPane.showMessageDialog(mainframe, "Kein Projekt verfügbar");
    else
    {
      CreateScriptDialog csd = new CreateScriptDialog(mainframe, p);
      csd.setVisible(true);
    }
  }

  /**
   * Öffnen des Projektdialogs mit dem übergebenen Projekt.
   */
  private Project openProjectDialog(Project proj)
  {
    ProjectDialog pd = new ProjectDialog(mainframe, proj);
    pd.setVisible(true);
    if(pd.isChanged())
      return pd.getProject();

    return null;
  }

  /**
   * Benachrichtigen des Menüs über die Änderung der Projekthistorydateienanzahl.
   */
  public void notifyHistoryCountChanged()
  {
    menu.setProjectHistorySize(settings.getMaxProjectHistoryCount());
  }

  /**
   * @param e
   */
  private void showTableDialog(ActionEvent e)
  {
    TablePanel p = (TablePanel)e.getSource();
    /**
     * Öffnen des Dialogs zum Ändern der Tabelle.
     */
    TableDialog td = new TableDialog(mainframe, p.getTable(), mainframe.getDatabase());
    td.setVisible(true);
    if(td.isChanged())
      p.setTable(td.getTable());
  }

  /**
   * Hinzfügen eines Menüitems für Importe.
   */
  public void addImportPluginMenuItem(Action action)
  {
    menu.addImportMenuItem(action);
  }

  public void loadPlugins() throws Exception
  {
    if(pluginmanager == null)
      pluginmanager = new PluginLoader();
    pluginmanager.loadPlugins(settings.getPluginPath());
  }

  /**
   * @param importer
   */
  public void openDatabaseImportDialog(ProjectImporter importer)
  {
    if(importdialog == null)
      importdialog = new DatabaseImportDialog(mainframe);
    importdialog.openDialog(importer);
  }
  /**
   * Listener für die Änderungen am Designer.
   * 
   * @author Eagle Eye
   * 
   */
  private class DesignerChangeListener implements DesignerListener
  {
    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#projectedChanged(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void projectedChanged(DesignerChangeEvent e)
    {}

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#projectedAdded(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void projectedAdded(DesignerChangeEvent e)
    {
      menu.setProjectEnabled(true);
    }

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#projectedRemoved(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void projectedRemoved(DesignerChangeEvent e)
    {
      menu.setProjectEnabled(false);
    }

    public void tableAdded(DesignerChangeEvent e)
    {
      setDesignerPanelMouseClickMode(DesignerPanel.MOUSEMODE_NORMAL);
    }

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#tableChanged(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void tableChanged(DesignerChangeEvent e)
    {}

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#tableMoved(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void tableMoved(DesignerChangeEvent e)
    {}

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#tableRemoved(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void tableRemoved(DesignerChangeEvent e)
    {}

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#projectedSaved(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void projectedSaved(DesignerChangeEvent e)
    {}

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#relationAdded(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void relationAdded(DesignerChangeEvent e)
    {
      setDesignerPanelMouseClickMode(DesignerPanel.MOUSEMODE_NORMAL);
    }

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#relationChanged(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void relationChanged(DesignerChangeEvent e)
    {}

    /**
     * @see de.eagleside.databasedesigner.listener.DesignerListener#relationRemoved(de.eagleside.databasedesigner.event.DesignerChangeEvent)
     */
    public void relationRemoved(DesignerChangeEvent e)
    {}
  }

}

Menubar

 * Created on 18.02.2007
 * 
 * Copyright (c) 2007, Kay Czarnotta
 * 
 * All rights reserved.
 */
package de.eagleside.databasedesigner.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Vector;

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

import de.eagleside.databasedesigner.data.Settings;
import de.eagleside.databasedesigner.gui.actions.CloseProjectAction;
import de.eagleside.databasedesigner.gui.actions.NewProjectAction;
import de.eagleside.databasedesigner.gui.actions.OpenProjectAction;
import de.eagleside.databasedesigner.gui.actions.OpenProjectSettingsAction;
import de.eagleside.databasedesigner.gui.actions.SaveProjectAction;
import de.eagleside.swing.FileHistoryMenuItem;

/**
 * Hauptmenubar für den Designer
 * 
 * @author Eagle Eye
 * 
 */
public class MenuBar extends JMenuBar
{
  private static final Settings settings = Settings.getInstance();
  private static final MainController controller = MainController.getInstance();
  private JMenuItem saveasprojectmenuitem, saveprojectmenuitem, openprojectmenuitem, newprojectmenuitem;
  private JMenuItem closeprojectmenuitem, openprojectsettingsmenuitem;
  private JMenuItem settingsmenuitem, closemenuitem, imageexportmenuitem, scriptexportmenuitem;
  private JMenu exportmenu, importmenu;
  private FileHistoryMenuItem projecthistorymenu;

  private Action newprojectaction, openprojectaction, saveprojectaction, closeprojectaction, openprojectsettingsaction;

  /**
   * Erzeugen einer neuen Menubar.
   */
  public MenuBar()
  {
    JMenu filemenu = new JMenu("Datei");
    JMenu projectmenu = new JMenu("Projekt");

    newprojectaction = new NewProjectAction();
    openprojectaction = new OpenProjectAction();
    saveprojectaction = new SaveProjectAction();
    closeprojectaction = new CloseProjectAction();
    openprojectsettingsaction = new OpenProjectSettingsAction();

    // newprojectmenuitem = new JMenuItem();
    // openprojectmenuitem = new JMenuItem("Projekt laden");
    // saveprojectmenuitem = new JMenuItem("Projekt speichern");
    saveasprojectmenuitem = new JMenuItem("Projekt speichern unter ");
    settingsmenuitem = new JMenuItem("Einstellungen");
    closemenuitem = new JMenuItem("Beenden");
    exportmenu = new JMenu("Export");
    importmenu = new JMenu("Import");
    imageexportmenuitem = new JMenuItem("Als Bild");
    scriptexportmenuitem = new JMenuItem("Als Script");

    // filemenu.add(newprojectmenuitem);
    newprojectmenuitem = filemenu.add(newprojectaction);
    openprojectmenuitem = filemenu.add(openprojectaction);
    saveprojectmenuitem = filemenu.add(saveprojectaction);
    filemenu.add(saveasprojectmenuitem);
    filemenu.addSeparator();
    filemenu.add(exportmenu);
    filemenu.add(importmenu);
    filemenu.addSeparator();
    filemenu.add(settingsmenuitem);
    filemenu.add(projecthistorymenu = new FileHistoryMenuItem("Letzte Projekte"));
    filemenu.add(closemenuitem);

    projectmenu.add(newprojectaction);
    projectmenu.add(openprojectaction);
    projectmenu.add(saveprojectaction);
    closeprojectmenuitem = projectmenu.add(closeprojectaction);
    openprojectsettingsmenuitem = projectmenu.add(openprojectsettingsaction);

    exportmenu.add(imageexportmenuitem);
    exportmenu.add(scriptexportmenuitem);

    add(filemenu);
    add(projectmenu);

    controller.setMenuBar(this);

    filemenu.setMnemonic(KeyEvent.VK_D);
    projectmenu.setMnemonic(KeyEvent.VK_P);
    newprojectmenuitem.setMnemonic(KeyEvent.VK_N);
    openprojectmenuitem.setMnemonic(KeyEvent.VK_O);
    openprojectmenuitem.setMnemonic(KeyEvent.VK_S);
    closeprojectmenuitem.setMnemonic(KeyEvent.VK_W);

    newprojectmenuitem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK));
    openprojectmenuitem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK));
    saveprojectmenuitem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK));
    closeprojectmenuitem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_MASK));

    imageexportmenuitem.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        controller.exportImage();
      }
    });
    scriptexportmenuitem.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        controller.exportScript();
      }
    });
    saveasprojectmenuitem.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        controller.saveProjectAs();
      }
    });
    closemenuitem.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        controller.close();
      }
    });
    settingsmenuitem.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        controller.showSettings();
      }
    });
    projecthistorymenu.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        controller.openProject(e.getActionCommand());
      }
    });

    importmenu.setVisible(false);
    projecthistorymenu.setFiles(settings.getProjectHistory());
    setProjectEnabled(false);
  }

  /**
   * Setzen der Historygröße für die Projekte.
   */
  public void setProjectHistorySize(int i)
  {
    projecthistorymenu.setMaximumItems(i);
  }

  /**
   * Hinzufügen einer neuen Datei für die Projekthistory.
   */
  public void addProjectHistoryFile(String f)
  {
    projecthistorymenu.addFile(f);
  }

  /**
   * Hinzufügen einer neuen Datei für die Projekthistory.
   */
  public void addProjectHistoryFile(File f)
  {
    projecthistorymenu.addFile(f);
  }

  /**
   * Setzen der Projekthistory Dateien.
   */
  public void setProjectHistoryFiles(Vector<String> files)
  {
    projecthistorymenu.setFiles(files);
  }

  /**
   * Löschen der Datei aus der Projekthistory.
   */
  public void removeProjectHistoryFile(File f)
  {
    projecthistorymenu.removeFile(f);
  }

  /**
   * Aktivieren aller Menüs, für die ein Projekt nötig ist.
   */
  public void setProjectEnabled(boolean b)
  {
    saveprojectaction.setEnabled(b);
    saveasprojectmenuitem.setEnabled(b);
    closeprojectaction.setEnabled(b);
    openprojectsettingsaction.setEnabled(b);
    exportmenu.setEnabled(b);
  }

  /**
   * Speichern der Menubardaten.
   */
  public void save()
  {
    settings.setProjectHistory(projecthistorymenu.getFiles());
  }

  /**
   * Hinzufügen eines neuen Menuitems für Importe.
   */
  public void addImportMenuItem(Action action)
  {
    importmenu.setVisible(true);
    if(action.getValue(Action.NAME) != null)
      for(int i = 0; i < importmenu.getComponentCount(); i++)
        if(((JMenu)importmenu.getComponent(i)).getText().compareToIgnoreCase(
            action.getValue(Action.NAME) != null ? String.valueOf(action.getValue(Action.NAME)) : "") < 0)
        {
          importmenu.add(new JMenuItem(action), i);
          return;
        }
    importmenu.add(action);
  }

  /**
   * Hinzufügen eines neuen Menuitems für Exporte.
   */
  public void addExportMenuItem(Action action)
  {
    exportmenu.setVisible(true);
    if(action.getValue(Action.NAME) != null)
      for(int i = 0; i < exportmenu.getComponentCount(); i++)
        if(((JMenu)exportmenu.getComponent(i)).getText().compareToIgnoreCase(
            action.getValue(Action.NAME) != null ? String.valueOf(action.getValue(Action.NAME)) : "") < 0)
        {
          exportmenu.add(new JMenuItem(action), i);
          return;
        }
    exportmenu.add(action);
  }
}

Danke erstmal! Ich denke, das Beispiel hat mir für das Grundkonzept für die Verwaltung eines Programms viel geholfen.

[QUOTE=deathbyaclown]Man sollte eher an Dependency Injection oder aehnliches nutzen (entweder selbst anleihern oder PICO oder Spring oder aehnliches verwenden )
)

zum einen gehts ja nicht um ein Objekt, sondern um ein Projekt… zum anderen muss man natuerlich nicht gleich Spring aufsetzen - Google Guice geht auch oder eben einfach selbst organisieren…[/QUOTE]
Was bringen diese ganzen Libs - ich vermute mal Libs, die einem helfen sollen, das Programm zu verwalten - bzw. was für Funktionen haben sie, dass sie Projekten verschiedener Arten „nützlich“ sein können?

Ich probiere jetzt erstmal EagleEyes Variante aus, nachdem ich einen blöden Bug gefixt habe… :slight_smile:

Gruß,
pcworld

sie helfen dir vernuenftig und sinnvoll zu programmieren…

was bringt es dir beim erfinden eines Autos die Reifen von Michelin oder so von anderen zu verwenden ?

gleiche frage…

achja - Eagle… sagt dir „Noise Comments“ was ? :stuck_out_tongue:

Sometimes you see comments that are nothing but noise. The restate the obvious and provide no new information.

  /**
   * Default constructor
   */
  public MyClass() {
  }

no, really ? Or how about this:

/** The day of the month */
private int dayOfMonth

And then there is this paragon of redundancy

 * Returns the day of the month
 * 
 * @return the day of the month
 */
 public int getDayOfMonth() {
    return dayOfMonth
 }

irgendwer hat mal irgendwann gesagt - „und kommentiere ja schoen ALLES aus“ - darausfolgerten immer unnuetze und unsinnige Kommentare… (Zitat uebrigens aus Clean Code - Robert C. Martin)

aber das hier sollte kein gespamme von Softwareentwicklung sein :wink:

verzeiht mein einschreiten - viel erfolg pcworld fuer das eigentliche problem !

Hey immerhin hab ich Kommentare :wink:
Das ist eine riesen Steigerung zu früher wo es nie welche gab :smiley:

[QUOTE=EagleEye]Hey immerhin hab ich Kommentare :wink:
Das ist eine riesen Steigerung zu früher wo es nie welche gab :D[/QUOTE]
hust aber wie gesagt - noise comments… und die erschweren eher die lesbarkeit des codes…

naja egal… bygones