# Exception: Adding a window to a container



## texton (29. Jan 2009)

Ich habe folgende Klassen (gekürzt) in einem MVC-Schema erstellt:

```
public class Main
implements IF
{
	public static void main( String[] saArgs )
	{
		// Instantiate a controller with its view. 
		new Controller( new Model(), new View() ).setVisible( true ); // #2
	}
}
```


```
public class Model
{
	public Model()
	{}
}
```


```
public class View
extends JFrame
implements IF
{
	private JPanel panDesktop = null;

	public View()
	{
		super();
		initialize();
	}

	private void initialize()
	{
		this.setSize( 700, 400 );
		this.setContentPane( getPanDesktop() );
	}

	private JPanel getPanDesktop()
	{
		if( null == panDesktop )
		{
			panDesktop = new JPanel( new BorderLayout() );
		}
		return panDesktop;
	}
}
```


```
public class Controller
extends JFrame
implements IF
{
	final Model oModel;
	private final View oView;

	public Controller( Model oNewModel, View oNewView )
	{
		super();
		this.oModel = oNewModel;
		this.oView = oNewView;
		setContentPane( this.oView ); // #1
	}
}
```
Beim Ausführen erhalte ich die Meldung:

```
Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
```
mit Verweis auf die Codezeilen #1 und #2
Ich komme nicht dahinter, wie ich es richtig machen muss.


----------



## SlaterB (29. Jan 2009)

2x extends JFrame  in einem Programm, welches nur ein Fenster anzeigen soll,
ist naturgemäß allgemein nicht gut,

-----

konkret:
an setContentPane() darst du kein JFrame übergeben, lasse View z.B. ein JPanel sein

die Befehle
> this.setSize( 700, 400 ); 
>      this.setContentPane( getPanDesktop() ); 
in View müssen dann wahrscheinlich umgebaut werden, der letztere auf jeden Fall,

JFrame in JFrame geht nicht, 
schau die JInternalFrame an, wenn du verschachtelte Fenster anzeigen willst


----------



## Ebenius (29. Jan 2009)

:autsch: Du fügst Deine View (ist ein JFrame) Deinem Controller (auch ein JFrame) hinzu. Man kann Komponenten auf ein Frame packen. Aber keine Fenster!

Anbei: Du hast irgendwas mit MVC in den falschen Hals bekommen. Ein Controller ist doch kein JFrame... Das ergibt genau null Sinn. Den Rest habe ich mir nicht angeschaut.

Ebenius


----------



## texton (29. Jan 2009)

Das MVC-Schema ist soweit richtig und wurde erfolgreich woanders schon angewendet.

Ursache des Problems war tatsächlich der doppelte Frame. Der View-Teil ist als virtuelle Klasse mit dem Visual Editor angelegt worden. Ich hatte als Basisfenster einfach JFrame ausgewählt, ohne daran zu denken, dass ich dies schon für den Controller-Teil gemacht hatte. Nach der Korrektur auf ein JPanel funktioniert jetzt alles.

Danke an euch beide!


----------



## Ebenius (29. Jan 2009)

texton hat gesagt.:
			
		

> Das MVC-Schema ist soweit richtig


Das glaubst nur Du. ;-)


----------



## texton (29. Jan 2009)

Was konkret soll am Schema falsch sein? Es ist seit Jahren im Einsatz und wurde von einem Experten geschrieben.


----------



## Ebenius (29. Jan 2009)

Anonymous hat gesagt.:
			
		

> Es ist seit Jahren im Einsatz und wurde von einem Experten geschrieben.


"Controller extends JFrame". Das finde ich falsch. 

Aber vielleicht ist der Name Controller hier aus einem anderen Grund verwendet worden, den ich nur nicht verstehe.


----------



## texton (29. Jan 2009)

Auch ich finde den JFrame im Controller-Teil merkwürdig, wo doch nur der View-Teil für die Darstellung zuständig sein soll. Ich habe aber nicht so viel Erfahrung mit MVC-Schemas und habe deshalb ein funktionierendes für meine Zwecke abgewandelt.

Den Quellcode habe ich übrigens an folgenden Stellen abgewandelt:

```
public class View
extends JPanel
implements IF
{
   public View()
   {
      super();
      initialize();
   }

   private void initialize()
   {
      this.setSize( 700, 400 );
      this.setLayout( new BorderLayout() );
   }
}
```
und

```
public class Controller
extends JFrame
implements IF
{
   final Model oModel;
   private final View oView;

   public Controller( Model oNewModel, View oNewView )
   {
      super();
      this.oModel = oNewModel;
      this.oView = oNewView;
      setPreferredSize( new dimension( 700, 400 ) );
      setSize( 700, 400 ); // zusammen mit obiger Zeile, weil Java sonst Zicken macht
      setContentPane( this.oView );   }
}
```
Wie sollte ich den Code abändern, damit im Controller-Teil das "extends JFrame" entfällt?


----------



## Ebenius (29. Jan 2009)

Anonymous hat gesagt.:
			
		

> Wie sollte ich den Code abändern, damit im Controller-Teil das "extends JFrame" entfällt?


Würde ich gar nicht. Ich würde die Klasse einfach MainFrame oder dergleichen umbenennen. Und da wir beim Umbenennen sind: Sofern "IF" ein Interface von Dir ist; der Name ist Mist, weil sagt nix.

Ebenius


----------



## SlaterB (29. Jan 2009)

je nach Aufgabe des Controllers könnte auch der View direkt das JFrame sein und der Controller von nix erben


----------



## texton (30. Jan 2009)

@Ebenius: Ja, "IF" steht für mein Interface. Ich habe alle Namen im Beispiel gekürzt; real sind sie natürlich aussagekräftiger.

@Ebenius + SlaterB: Der Controller hat im MVC-Schema die Aufgabe, Aktionen des Users zu verarbeiten, während das View für die Darstellung des Interfaces zuständig ist. Dennoch muss der Controller ja auf das in View definierte User Interface zugreifen können, denn wie sonst sollte er erfahren, ob er was zu tun hat? Deshalb die Art des Aufrufs in der Main.

Wenn ich das umsetzen würde


> je nach Aufgabe des Controllers könnte auch der View direkt das JFrame sein und der Controller von nix erben


wie sollte dann der Controller auf Ereignisse reagieren können? (Umgeschriebenes Beispiel wäre dann hilfreich.)


----------



## SlaterB (30. Jan 2009)

was heißt denn 'umgeschrieben', deine Vorgabe ist doch gänzlich ohne Ereignisbehandlung 

die technische Ereignisbehandlung, also einen ActionListener an einem Button zu adden, kann im View stattfinden,
nur sollte die dann nicht wissen, was zu tun ist, sondern dem Controller beispielsweise mitteilen:
controller.loginButtonGedrueckt();

ob dabei schon beispielsweise die Strings aus dem Name- + Passwort-Feld mitübergeben werden, 
oder ob der Controller das selber bei der View noch abfragen muss, ist eher nebensächlich,

wichtig ist dann, dass der Controller die logische Arbeit übernimmt wie DB-Abfragen nach dem User (oder einfach nur im 'Model' nachschauen), 
Rechtekontrolle, irgendwelche anzuzeigenden Daten laden usw.,

das alles ist unabhängig von dem View, beispielweise bei einer Webanwendung mit HTML-Seiten genauso auszuführen,
daher ein Fall für eine Klasse, die nicht von JFrame erbt

gewisse Übergangsaufgaben wie das erwähnte Einlesen von Daten oder Anzeige von Ergebnissen sind fließend zwischen Controller und View anzusiedeln


----------



## texton (30. Jan 2009)

@SlaterB: Ich versuche mal alles zu verstehen (nicht leicht bei den streitenden Mitarbeitern hier ...).

Aufrufe wie


> controller.loginButtonGedrueckt();


sind klar.


> das alles ist unabhängig von dem View, (...), daher ein Fall für eine Klasse, die nicht von JFrame erbt


Das war ja genau meine Frage aus dem letzten Post. Mein controller erbt derzeit noch von JFrame. Ich sehe derzeit nicht, wie ich es so umstellen kann, dass das nicht mehr der Fall ist. Dazu müsste doch auch die main angepasst werden, oder? Deshalb meine Bitte, mir hier konkrete Hilfe zu geben, damit mein Controller sich wirklich nur um die Verarbeitung kümmert.


----------



## SlaterB (30. Jan 2009)

```
public class Test
{
    public static void main(String[] args)
    {
        View v = new View();
        new Controller(new Model(), v);
        v.setVisible(true);
    }
}


class Controller
{
    final Model oModel;
    private final View oView;

    public Controller(Model oNewModel, View oNewView)
    {
        super();
        this.oModel = oNewModel;
        this.oView = oNewView;
    }
}


class View
    extends JFrame
{
    public View()
    {
        super();
        initialize();
    }

    private void initialize()
    {
        this.setSize(700, 400);
        this.setLayout(new BorderLayout());
    }
}


class Model
{
    public Model()
    {
    }
}
```


----------



## texton (30. Jan 2009)

Vielen Dank für die Geduld :applaus: . Ja, ist tatsächlich ganz einfach    (sich im Büro hier zu konzentrieren ist schon ein Kunststück :cry: .


----------

