# Swing und MDI mit JInternalFrame



## goodcat (6. Jan 2012)

Hi,

ich schreibe gerade eine Anwendung die MDI fähig sein soll und auf dem MVC Pattern aufgebaut ist (jedenfalls versuche ich das).
Ich verwende für die "MainGui" ein JFrame und für die Fenster die sich in dem JFrame öffnen sollen habe ich JInternalFrames benutzt.

Jetzt erstmal die Frage ob das soweit korrekt ist. Oder ob es "schönere" Varianten gibt eine MDI zu programmieren.
JFrame mit JDesktopPane und dann JInternalFrame auf JDesktopPane adden.

So und jetzt muss ich ja um ein JInternalFrame auf dem JFrame anzuzeigen ein JDesktopPane im JFrame hinzufügen und das JInternalFrame dort adden. Aber da gibt es ein Problem denn wenn ich aus einem JInternalFrame ein weiteres JInternalFrame öffnen möchte habe ich ja kein Zugriff mehr auf den JDesktopPane (der sich im JFrame befindet) um dort das neue Fenster zu adden (desktopPane.add())...

Jetzt habe ich gedacht das mir an der Stelle bestimmt das Observer Pattern weiterhelfen könnte, wenn das überhaupt geht bzw. sinnvoll ist?!... *Aber wie geht man in solchen fällen am besten vo*r. Ich möchte nicht unbedingt das JDesktopPane von Klasse zu Klasse weiterreichen und ich glaube das ist auch keine besonders gute Lösung!

Danke
Goodcat


----------



## goodcat (7. Jan 2012)

Also ich habe jetzt folgendes gemacht um die JnternalFrame auf das JDesktopPane zu adden.

Ich habe das JDesktopPane welches in der View instanziert wird, privat und statisch angelegt:
MainAppView.java

```
private static final JDesktopPane desktopPane = new JDesktopPane();

public static JDesktopPane getInstance() {
	return desktopPane;
}
```

Dann noch einen getter der mir die Instanz des Objektes liefert, also nach dem Singelton Prinzip. Die MainApp (View, Controller, Model).java ist das JFrame welches die ganzen JInternalFrames beinhaltet.

Damit kann ich aus dem gesammten Programm immer auf das JDesktopPane zugreifen und JInternalFrames adden.

Was meint ihr dazu? Ist das so sinnnvol bzw. sauber oder wiederspricht das dem MVC?

Danke Goodcat


----------



## GUI-Programmer (7. Jan 2012)

goodcat hat gesagt.:


> Was meint ihr dazu? Ist das so sinnnvol bzw. sauber oder wiederspricht das dem MVC?



Sinnvoll ist es meiner Meinung nach.

Sauber nicht ganz. Ist nicht ein Stil den ich als sauber oder elegant erkären würde, dennoch besser als manch andere Art und Weise, die ich hier im Forum schon erlebt habe, an das Problem zu gehen.

MVC - kommt darauf an, ob die View dein JInternalFram "kennt" und der Controller darauf über die View darauf zugreifen kann.


----------



## goodcat (7. Jan 2012)

Naja dann bin ich ja einigermaßen froh das die Idee nicht totaler Müll ist 

Da die View und der Controller getrent sind kennt meine View das neue JInternalFrame nicht. In der View befindet sich ein Button, wenn ich den drücke wird das Ereignis im Controller verarbeitet und es wird ein neues JInteralFrame erstellt. Damit ist dem Controller der MainApp der Controller des JInternalFrames bekannt... Im Controller wird bei mir die View und das Model instanziert. 

Also hat jedes JInternalFrame seinen eigenen Controller, View und Model... Ist das so korrekt?

Oder sollte ich das neue JInternalFrame (also den Controller der JInternalFrame) in der View der MainApp erstellen?

Was würdest Du denn als elegant oder sauber bezeichnen, wie würdest Du das lösen?


----------



## GUI-Programmer (7. Jan 2012)

View:

```
public class View {
	private Model model;
	private Controller controller;
	protected JInternalFrame internalFrame;
	protected JButton btnOpenInternalFrame;
	//...weitere Komponenten
	public View(Model model) {
		this.model = model;
		controller = new Controller(this, model);
		internalFrame = new JInternalFrame();
		internalFrame.setVisible(false);
		// internalFrame einstellen, konfigurieren, etc.
		// internalFrame hinzufügen
		btnOpenInternalFrame = new JButton("Open the Frame");
		// btnOpenInternalFrame einstellen, konfigurieren, etc.
		btnOpenInternalFrame.addActionListener(controller);
		// weitere Komponenten, etc.
	}
}
```

Controller:

```
public class Controller implements ActionListener /* weitere Listener*/ {
	private View view;
	private Model model;
	public Controller(View view, Model model) {
		this.view = view;
		this.model = model;
	}
	
	@Override
	public void actionPerformed(ActionEvent evt) {
		if(evt.getSource().equals(view.btnOpenInternalFrame)) {
			view.internalFrame.setVisible(true);
		}
	}
}
```

Für mehr Informationen zum Thema MVC siehe mein Beispiel aus meiner Signatur.


----------



## goodcat (7. Jan 2012)

Aha ok das heisst Du erstellst den Controller und das Model in der View? Das habe ich so nocht nicht gesehen.
Und das JinternalFrame in der View zu instanzieren umgeht natürlich das Problem mit dem adden auf die JDesktopPane. Ausser ich möchte aus einem JInternalFrame ein weiteres JInternalFrame erstellen und das war ja mein anfängliches Problem.

Verstehe ich das richtig das es für jedes JInternalFrame was instanziert wird es nur den einen Controller und das eine Model gibt?
Denn ich hatte mir das so überlegt für jedes JInternalFrame einen extra Controller und Model zu bauen.

Da es eine MDI Anwendung werden soll interessiert es mich natürlich ob für jedes JInternalFrame ein komplet neuer Controller und Model zu erstellen ist.


----------



## GUI-Programmer (8. Jan 2012)

goodcat hat gesagt.:


> Verstehe ich das richtig das es für jedes JInternalFrame was instanziert wird es nur den einen Controller und das eine Model gibt?
> Denn ich hatte mir das so überlegt für jedes JInternalFrame einen extra Controller und Model zu bauen.



Nein nicht unbedingt nur einen Controller, war nur in meinen Beispiel so. Wenn es be deinen Fall sinnvoller ist mehrere Controller zu besitzen, dann spricht da auch nichts dagegen. Schließlich beinhaltet MVC nur eine kompplette Trennung von den Bereichen, also in Java am besten durch benutzen von vers. Klassen für jeden Bereich. Was nicht heißt, das jeder Bereich nur "eine Klasse groß ist".

Und Übrigens, das Model wird nicht in der View instanziert. Sondern bei der ausführbaren Klasse. Die erzeugte Instanz wird an der View bei deren Erstellung über den Konstruktor übergeben.



goodcat hat gesagt.:


> Ausser ich möchte aus einem JInternalFrame ein weiteres JInternalFrame erstellen und das war ja mein anfängliches Problem



Mein erster Gedanke wäre bei sowas ne ArrayList<JInternalFrame> in der View zu haben. Danach nach Belieben hinzufügen und entfernen.


----------



## goodcat (8. Jan 2012)

> Und Übrigens, das Model wird nicht in der View instanziert. Sondern bei der ausführbaren Klasse. Die erzeugte Instanz wird an der View bei deren Erstellung über den Konstruktor übergeben.



Oh ja stimmt, hätte ich mir mal etwas genauer den Konstruktor anschauen sollen 

Eine ArrayList<JInternalFrame> in der MainAppView... mh aber dann hab ich ja immernoch das Problem das ich irgendwie auf die Liste zugreifen muss... Eine ArrayLIst in der View und eine Methode die das entsprechene JInternalFrame an den Desktop added, oder sowas in der Art ???:L

Müsste dann ja statisch sein, damit ich von überall darauf zugreifen kann?!


----------



## GUI-Programmer (8. Jan 2012)

goodcat hat gesagt.:


> Eine ArrayLIst in der View und eine Methode die das entsprechene JInternalFrame an den Desktop added, oder sowas in der Art ???:L!



Ja genau, so in etwa.



goodcat hat gesagt.:


> Müsste dann ja statisch sein, damit ich von überall darauf zugreifen kann?!



Nee auf gar keinen Fall statisch. Bei MVC braucht doch eh nur die View und der Controller was von den JInternalFrames zu wissen. Beim Erstellen von neuen JInternalFrames musst du halt View & Controller mit übergeben.


----------



## goodcat (8. Jan 2012)

Mh ok dann werde ich mir den Code nochmal genauer anschauen.

Was genau für ein MVC Pattern hast Du denn gepostet? Also es gibt ja verschiedene Varianten so wie ich das verstanden habe.


----------



## bERt0r (8. Jan 2012)

Also ich versteh das Problem hier nicht. Du hast einen Frame. In dem Frame liegt eine DesktopPane. Im DesktopPane liegen Internalframes. Wenn deine Internalframes eigene Klassen sind, die eine Methode haben z.B "openNewInternalFrame()", dann musst du der Internalframeklasse eben eine Referenz der DesktopPane übergeben, z.B im Konstruktor. Mit MVC hat das ganze nicht wirklich was zu tun, was wäre denn hier das Model?
[Edit]Es gibt sogar die funktion getDesktopPane bei InternalFrames, die genau das macht[/Edit]


----------



## goodcat (9. Jan 2012)

Moin,

also ein Problem git es eigentlich nicht mehr.
Ich hatte fragen zur Struktur bei einer MDI Anwendung die das MVC Pattern benutzen soll. 
Denn um ein JInternalFrame anzuzeigen muss es ja dem JDesktopPane geadded werden und da hatte ich fragen wie dies zu gestalten ist wenn aus einem JInternalFrame ein weites JInternalFrame geöffnet werden soll.



> Es gibt sogar die funktion getDesktopPane bei InternalFrames, die genau das macht



Das ist ja super die Methode kannte ich garnicht :bahnhof:
Dann kann ich mir das übergeben der View oder des Controllers an das JinternalFrame ersparen. Cool Danke! :toll:

Vielen Dank an euch beide!
Goodcat


----------

