# MVC: controller in unabhängigen thread von der view starten (gui friert ein)



## Buyakasha (8. Aug 2009)

Hallo,

ich versuche ein Poker-Programm der Hold'em Texas-Variante zu programmieren und möchte mich dabei strikt an das MVC-Konzept halten. 
Dabei bin ich auf das Problem gestoßen, dass meine GUI einfriert, während Code des Controllers ausgeführt wird. Nach einigem googlen und lesen hier im Forum habe ich dann heraus gefunden, dass es wohl daran liegt, dass der Code des Controllers auch im EventDispatchThread ausgeführt wird. 

Dann habe ich nach einer Lösung gesucht, wie man am besten den Controller und die View in eigene Threads aufteilt.
Folgender Beitrag kam meinem Problem am nächsten: http://www.java-forum.org/java-basics-anfaenger-themen/35878-graphical-user-interface-friert-waerend-programmdurchlauf-ein.html

Leider funktioniert dort der Link zu der MVC-Anleitung nicht mehr und der Lieblingslink im Beitrag von AlArenal weiter unten funktioniert bei mir auch nicht richtig. Dort komme ich zwar auf eine Seite und kann unten auf "Play" drücken, aber es passiert nichts. Habe das in mehreren Browsern ausprobiert. Wenn mir da jemand helfen kann wieso das nicht funktioniert ist mir vll. auch schon geholfen 

Ansonsten währe ich dankbar für jeden Tipp oder Link, wie ich den Controller am besten in einen eigenen Thread packe. 

Hier noch ein Beispiel zu dem Design, dass ich gewählt habe:
[Java]
class Main
{
	public static void main(String[] args)
	{
		SwingUtilities.invokeLater(new Runnable() {
			public void run()
			{
				GameGUI gui = new GameGUI();

				new GameListener(gui);

				gui.setVisible(true);
			}
		});
	}
}

// Controller
class GameListener
{
	private GameGUI gui;
	private Game game;

	public GameListener(GameGUI gui, Game game)
	{
		this.gui = gui;
		this.game = game;
		this.game.addGameListener(this);
	}

	// hier sind Methoden wie startGame(); und playRound();
}

// View
class GameGUI extends JFrame
{
	// GUI-Componenten als Instanzvariablen

	public GameGUI()
	{
		// Konstruktor sorgt dafür, dass die Componenten passend angeordnet werden etc.
	}
}

// Model
class Game
{
	private int playerTurn;
	private int round;
	// weitere Instanzvariblen das Spiel betreffend 

	public Game()
	{
		// setzen der Instanzvariablen
	}

	public addGameListener(GameListener gl)
	{
		// Methode zum hinzügen eines GameListeners
	}

	public removeGameListener(GameListener gl)
	{
		// Methode zum entfernen eines GameListeners
	}
}
[/code]

Habe es versucht nur das zum Verständnis nötige hinzuzufügen. Wenn hier aber noch Erklärungen gebraucht werden, bitte einfach fragen 

Vielen Dank fürs lesen.


----------



## Painii (8. Aug 2009)

Buyakasha hat gesagt.:


> Dann habe ich nach einer Lösung gesucht, wie man am besten den Controller und die View in eigene Threads aufteilt.



Einfach den Controller das Interface Runnable implementieren lassen.
Dann kannst du einen neuen Thread daraus bauen und den starten.


```
public class Controller() implements Runnable{
 public Controller(){
  //Model setzen und den ganzen Spass
 }
 public void run(){
  //wird durch start() eines Threads aufgerufen
  while(game_runs){
   //Das Model verändern
  }
 }
}

public staic void main(String[] args){
 Controller controller = new Controller();
 Thread controllerThread = new Thread(controller);
 controllerThread.start();
}
```


----------



## Buyakasha (8. Aug 2009)

Hallo Painii,

danke für deine Antwort 

Ich habe allerdings mehrere Listener-Klassen die zusammen das Controller-Packet ergeben. Also für jeden Button habe ich eine eigene Listener-Klasse geschrieben. Ich habe mich da an ein MVC-Beispiel gehalte, dass ich mal geschickt bekommen habe. 

Wenn sich das jemand mal genauer anschauen möchte: Dateiupload - dein kostenloser Filehost


----------



## Dissi (9. Aug 2009)

Evt eine Starter klasse für controller bauen welche Runable ist


----------



## Buyakasha (9. Aug 2009)

Hallo Dissi,

die Idee gefällt mir  Weiß zwar noch nicht genau wie ich das umsetzen soll, aber ich werde es mal versuchen...


----------



## Buyakasha (13. Aug 2009)

Hallo,

ich habe jetzt versucht eine Starterklasse zu schreiben in der ein extra Thread gestartet wird. 

Hier der Code:

```
import javax.swing.SwingUtilities;

import model.Game;

import controller.CallListener;
import controller.CheckListener;
import controller.FoldListener;
import controller.GameGUIWindowListener;
import controller.GameListener;
import controller.RaiseListener;
import controller.StartGameListener;
import view.GameGUI;
import view.MenuGUI;

public class Main implements Runnable
{
	private static MenuGUI menuGUI;
	private static GameGUI gameGUI;
	private static Game game;
	
	public static void main(String[] args)
	{	
		game = new Game();
		new Main().startApplication();
	}
	
	public void startApplication()
	{
		SwingUtilities.invokeLater(new Runnable() {
			public void run()
			{
				menuGUI = new MenuGUI();
				gameGUI = new GameGUI(game);
			}
		});

		new Thread(this).start();
		
		menuGUI.setVisible(true);
	}

	@Override
	public void run() {
		new StartGameListener(game, menuGUI, gameGUI);
		
		new GameListener(gameGUI, game);
		new GameGUIWindowListener(gameGUI, menuGUI, game);
		new CallListener(game, gameGUI);
		new CheckListener(game, gameGUI);
		new FoldListener(game, gameGUI);
		new RaiseListener(game, gameGUI);
	}
}
```

Allerdings funktioniert das so noch nicht, denn ich habe eine NullPointerException.

Exception in thread "Thread-2" java.lang.NullPointerException
	at controller.StartGameListener.<init>(StartGameListener.java:27)
	at Main.run(Main.java:46)
	at java.lang.Thread.run(Unknown Source)

Ich gehe davon aus, dass menuGUI und gameGUI noch nicht erstellt wurden... wie kann ich sicher stellen, dass die erstellt werden bevor im anderen Thread die Listenener-Objekte erstellt werden?

Vielen Dank für alle Hinweise.


----------

