# Trennung von GUI und Logik



## Kaffeetrinker79 (27. Sep 2006)

Hallo,
ich habe ein recht einfaches Problem, aber ich bekomme es einfach nicht hin.
Wie kann ich GUI und Logik sauber trennen?
Als Beispiel habe ich folgendes einfaches Beispiel geschrieben:


Hauptklasse: 


```
public class mainclass {
    public static void main(String[] args) {
        meinfenster fenster = new meinfenster();
    }
   
    public static void test(){
        System.out.println("test");
    }
}
```

GUI-Klasse:

```
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class meinfenster extends JFrame implements ActionListener{
    public meinfenster() {
        this.setSize(300,100);
        this.setLocation(200,200);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void jbInit() throws Exception {
        ibutton1.setText("TestButton");
        ibutton1.addActionListener(this);
        jLabel1.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel1.setHorizontalTextPosition(SwingConstants.CENTER);
        jLabel1.setText("Test");
        this.getContentPane().add(ibutton1, java.awt.BorderLayout.SOUTH);
        this.getContentPane().add(jLabel1, java.awt.BorderLayout.CENTER);
        this.show();


    }

    JButton ibutton1 = new JButton();
    JLabel jLabel1 = new JLabel();
    public void actionPerformed(ActionEvent e) {

}

}
```
Nun meine Frage: Wie kann ich aus der GUI Klasse heraus die Methode test() aufrufen ohne das dabei die Mainclasse wieder den Actionlistener implementieren muss? Dazu muss das Event aus der GUI-Klasse ja an die mainclasse zurückgeliefert werden. Wie geht das?


----------



## hupfdule (27. Sep 2006)

Indem du deiner GUI-Klasse eine Referenz auf die Logikklasse mitgibst. Am besten gleich im Konstruktor. Diese kann dann aus dem ActionListener heraus deren test() aufrufen.

Um das noch etwas sauberer zu handhaben (was allerdings nur in größeren Projekten lohnt), könnte die Logikklasse noch ein Interface implementieren und die GUI-Klasse erwartet dann nur eine Implementierung dieses Interfaces. Damit hättest du noch einmal die Abstraktion erhöht.

BTW: Laut Konventino werden Klassen in Java in PascalCase geschrieben. (MeinFenster statt meinfenster)


----------



## KSG9|sebastian (27. Sep 2006)

deine Logik sieht z.B. so aus


```
interface Logik{
  public void test();
  public void ende();
  public void action();
  // noch mehr methodenkörper
}

class LogikImpl implements Logik{
   public LogikImpl(){
      MeinFenster mf = new MeinFenster(this);
   }
   public void action(){
      System.out.println("action performed");
   }
   public void test(){
      // do something
   }
   public void ende(){
      System.exit(1);
   }
}
```

Und deine Klasse MeinFenster muss dann den Konstruktor "public MeinFenster(Logik l)" haben. Die Referenz zum Logik-Interface speicherst du als Instanzvariable und dann kannst du im actionlistener z.B. l.action() aufrufen.
Damit hast du dann die Trennung erreicht.


----------



## Kaffeetrinker79 (27. Sep 2006)

hupfdule hat gesagt.:
			
		

> Indem du deiner GUI-Klasse eine Referenz auf die Logikklasse mitgibst. Am besten gleich im Konstruktor. Diese kann dann aus dem ActionListener heraus deren test() aufrufen.
> 
> Um das noch etwas sauberer zu handhaben (was allerdings nur in größeren Projekten lohnt), könnte die Logikklasse noch ein Interface implementieren und die GUI-Klasse erwartet dann nur eine Implementierung dieses Interfaces. Damit hättest du noch einmal die Abstraktion erhöht.
> 
> BTW: Laut Konventino werden Klassen in Java in PascalCase geschrieben. (MeinFenster statt meinfenster)



Meintest Du das so? Funktionieren tut es jedenfalls. Das mit dem Interface werde ich jetzt auch nochmal probieren.

```
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class meinfenster extends JFrame implements ActionListener{
    mainclass neu; //<--- neue Zeile
    public meinfenster() {
        this.setSize(300,100);
        this.setLocation(200,200);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        neu = new mainclass(); //<--- neue Zeile
        try {
            jbInit();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void jbInit() throws Exception {
        ibutton1.setText("TestButton");
        ibutton1.addActionListener(this);
        jLabel1.setHorizontalAlignment(SwingConstants.CENTER);
        jLabel1.setHorizontalTextPosition(SwingConstants.CENTER);
        jLabel1.setText("Test");
        this.getContentPane().add(ibutton1, java.awt.BorderLayout.SOUTH);
        this.getContentPane().add(jLabel1, java.awt.BorderLayout.CENTER);
        this.show();
    }

    JButton ibutton1 = new JButton();
    JLabel jLabel1 = new JLabel();
    public void actionPerformed(ActionEvent e) {
        neu.test(); //<--- neue Zeile
}
}
```

Natürlich musste ich die Methode text() als nicht statisch ändern.


----------



## KSG9|sebastian (27. Sep 2006)

nein so erzeugst5 du aus der GUI heraus ne neue Logikklasse.
So war es gemeint (wie ich oben schon geschrieben hab)


			
				ICH hat gesagt.:
			
		

> deine Logik sieht z.B. so aus
> 
> 
> ```
> ...


----------



## hupfdule (27. Sep 2006)

> Meintest Du das so?


Nein. Du erzeugt in der GUI einen neuen Controller. Das ist nicht Sinn der Sache. Der Controller soll die GUI erzeugen. Und gleichzeitig teilt er der GUI mit, wer ihr Controller ist:


```
public class MeinFenster extends JFrame implements ActionListener{ 
    MainClass controller; //<--- neue Zeile 
    public meinfenster(MainClass controller) {
         this.controller= controller;
         ...
    }
}
```

Oder halt statt MainClass das entsprechende Interface.



> Natürlich musste ich die Methode text() als nicht statisch ändern.


Es gibt aber doch auch keinen Grund, warum diese statisch sein sollte?


----------



## Kaffeetrinker79 (27. Sep 2006)

Ahja, jetzt habe ich beide Möglichkeiten begriffen und erfolgreich implementiert.
Vielen Dank für die schnelle Hilfe.


----------

