# Warum baut man eine GUI nicht in der main-Methode?



## Semox (31. Dez 2008)

Hallo

Ich arbeite gerade eine eine Java-Lektion durch und es gibt haufenweise Einzelprobleme, mit denen ich z.Z konfrontiert bin. Das neue Jahr rückt näher und mit ihm die Semesterabschlußprüfungen. Leider habe ich eine sehr wichtige Frage, welche die Erstellung einer Anwendung betrifft, die eine GUI anzeigen soll. Ich bekomme das aber nicht so schnell hin, wie gedacht. Diese Anwendung stellt ein Fensterchen dar, in dem eine ungewisse Anzahl von farbig hinterlegten Checkboxen auftreten sollen, die durchgehend numeriert werden sollen und eine von den vielen Boxen soll aktiviert sein, während die anderen es nicht sind. ;-)

Wandle hierbei ein Applet zu einer Anwendung, bei der alle wichtigen Sachen in einem Konstruktor der Art liegen:


```
//Constructor using int size to display a number of Checkboxes
    public CheckAppAM(int size) {
        //What for do I need this? 

 
        //to fix the number of boxes as asked in the exercise
        // call the constructor of the superclass
        // has to be the first statement
        super("Checkboxes App");
        this.size = size;
}
```

Dabei erwähnte meine Professorin, daß ich einen Konstruktor verwenden soll, in dem alles Nötige initialisiert ist, was dann einmal später aufgerufen werde. Hierzu habe ich den Inhalt ihres Kommentars nicht begriffen:


```
public static void main(String[] args) throws IOException {

		// do not build the GUI here
		// use the constructor for that
		// In this exercise you are also suposed to learn a systematic way to transform an applet
		// into an application. A good way for the transformation is to put what belongs to the init
		// method of an pallet into the constructor.

//lots more code....
}
```

 :meld: 

Was ich nicht verstehe ist, warum baut man die Swing oder AWT Components nicht in die *main* Method? Leider bin ich nach weit mehr als einer Woche noch nicht dahinter gestiegen, weil mich zudem noch Probleme mit der IDE plagen, die ich nicht so richtig in den Griff bekomme. Alles in allem etwas verzwickte Lage und die Zeit verrinnt schneller als ich die Lösungen präsentiere. Ich will den Kram ja nicht immer nur husch-schnell hinwerfen müssen, sondern den tieferen Sinn der Java Sprache verstehen, damit ich irgendwann bald meine eigenen Patterns habe, mit denen ich gute Programme schreiben kann. :### 

Vielleicht kann mir jemand auch noch diese Randfrage beantworten: Weiß jemand warum es z.B. immer eine Warnung seitens Netbeans 6.5 gibt, das mich darauf hinweist innerhalb des Quellcodes eine "Add @Override annotation" einzufügen? Das ist mir nicht ganz klar.

Viele Grüße
Semox
-->...hat noch Zuversicht...


----------



## MyPiano (31. Dez 2008)

Hallo,

ich würde sagen, die Antwort für deine Erste Frage findet man in der Architektur von Java. die *main* Methode ist immer eine statische Methode und kann deshalb nicht auf Mitglieder nicht-statischer Methoden zugreifen. Daher musst du die Form immer über einen Konstruktor aufrufen.


```
public class Main extends JFrame {

 public static void main(String[] args) throws Exception {
       
        new Main();
     
    }
  
 public Main()
 {
  //Code zum Erstellen des Fensters
  }
 
 }
```

Die Override annotation ist im Grunde nur ein Hinweis für den Programmierer, das er eine bereits vorhandene Methode überschrieben hat. Warum das sinnvoll sein soll, kann ich dir auch nicht sagen, es könnte aber etwas mit der Dokumentation des Codes zu tun haben - wenn ein Javadoc erstellt wird. Es ist aber nicht notwendig und es wird keinen Syntaxerror oder Laufzeitfehler geben. Exceptions werden auch nicht geworfen. 

Ich hoffe ich konnte dir weiterhelfen.

Viele Grüße und guten Rutsch

MyPiano


----------



## 0x7F800000 (31. Dez 2008)

1) weil in die main normalerweise ziemlich nichts bis auf ein paar konstruktoren und initialisierungs/start-methodenaufrufe hingehört. Wenn da wesentlich mehr als 10 zeilen drinstehen, dann muss das projekt entweder recht umfangreich sein, oder man hat irgendwas nicht gut genug gegliedert.

2) das ist für programmierer gedacht, um zB. blöde schwer aufzufindende tippfehler zu vermeiden, etwa sowas:

```
addMouseMotionListener(new MouseMotionAdapter(){
  //kein @Override hier 
  public void mouseMoves(MouseEvent e){
     //tjaaa... soll sich doch der programmierer jetzt stundenlang wundern, warum nix passiert
   }
}
```
das ist schlecht. Compiler meldet keine fehler, alles scheint in Ordnung, aber bewegen tut sich trotzdem nichts. Wenn man dagegen @Override hinzufügt, dann wird der compiler sofort meckern, dass es die methode "mouseMoves" in der Oberklasse gar nicht gibt, dann schaut man in der API nochmal nach, und stellt fest, dass die Methode "mouseMoved" heißt, und die Welt ist gerettet.


----------



## André Uhres (31. Dez 2008)

Da bei der Initialisierung in der Regel Instanzvariablen angelegt werden,
muss sie im Konstruktor oder in einer nicht statischen Methode stattfinden.
Dazu kommt, daß die main auf dem Initial Thread läuft, die Gui aber auf dem Thread
laufen muss, welcher der graphischen Anzeige gewidmet ist (EventDispatchThread).
Die main muss also die Gui Initialisierung etwa so aufrufen:

```
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        createAndShowGUI();
    }
}
```
Siehe auch: http://java.sun.com/docs/books/tutorial/uiswing/concurrency/initial.html


----------



## Semox (31. Dez 2008)

Hallo André, Andrey und MyPiano

Vielen Dank für Eure Antworten. In der Schnittmenge Eurer Antworten lag für mich persönlich der Weisheit letzter Schluß. Super! Jetzt habe ich das verstanden... Ein wunderbarer Jahreswechsel sei Euch beschieden...

Liebe Grüße
Semox


----------



## 0x7F800000 (31. Dez 2008)

Semox hat gesagt.:
			
		

> In der Schnittmenge Eurer Antworten lag für mich persönlich der Weisheit letzter Schluß.


Schnitt? Vielleicht doch eher Vereinigung? 
Dass in der Leeren Menge die ganze Weißheit drin sein soll, ist schon ziemlich... Zen^^


----------



## Marco13 (1. Jan 2009)

Hast wohl noch nicht oft Antworten in Foren gesucht, oder? :wink: Wenn man von 5 Leuten etwas hört, ist fast immer irgendwo Mist dabei, aber der Kern, also die Schnittmenge, nämlich das, was bei allen gleich ist, ist meistens der Teil, auf den man sich am ehesten verlassen kann :wink:


----------



## André Uhres (1. Jan 2009)

Marco13 hat gesagt.:
			
		

> Wenn man von 5 Leuten etwas hört, ist fast immer irgendwo Mist dabei


 :lol:  :lol:  :lol: 
Der fünfte bist du!!!
 :lol:  :lol:  :lol:


----------



## 0x7F800000 (1. Jan 2009)

naja, hier war's ja nicht wirklich so... der eine redete von klassen/instanzen-zugriffsrechten, der andere von sinnvoller gliederung des codes, der dritte von concurrency in swing. Die Schnittmenge war irgendwie recht leer^^

Ansonsten würde ich auch etwa so vorgehen, dass man alle 2-3 Elementigen Teilmengen der Menge aller antworten nimmt, davon die Schnittmenge bildet, und anschließend alle Schnittmenge wieder vereining, so sollte man was sinnvolles rausbekommen


----------



## André Uhres (1. Jan 2009)

Ich weiss was weit, weit Besseres: die Antworten selbst prüfen und das behalten, was richtig ist!


----------



## Illuvatar (1. Jan 2009)

Marco13 hat gesagt.:
			
		

> aber der Kern, also die Schnittmenge



Hmm... der Kern?  Sofern ich in Algebra richtig aufgepasst hab hat der aber nix mit Schnittmengen zu tun :bae:

(Und auch mein erster Beitrag 2009 besteht mal wieder aus Unsinn. Nichts destotrotz: Gutes neues Jahr!)


----------



## Semox (1. Jan 2009)

Hallo Forum

Euch allen ein frohes neues Jahr!

Hier ist der Grund für die Nachfrage. Ich habe eine Anwendung, in der ich Checkboxes plazieren will und das nicht ging. Hier ist meine Anwendung... Das tollste ist ja, daß ich alles schön durchkommentiert habe.


```
package le08_checkboxen;

import java.util.Random;
import javax.swing.*;
import java.awt.*;
/**
 *
 * @author Sebastian Morkisch
 * @since 01.01.2009
 * @serial 1.0.1
 */
public class CheckApp extends JFrame {

    //Klassenattribute
    private int count = 0; //number of check boxes to add in the frame
    private Random r = new Random(); //Random number generator
    private JPanel panel;

    public CheckApp(int size) {
        //make new Frame

        //set location of window on screen
        this.setLocation(300, 200);

        //Set default close operation for the frame window
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //JPanel to hold JCheckBoxes
        this.panel = new JPanel();

        //Set the panel background as gray
        this.panel.setBackground(Color.LIGHT_GRAY);

        //Set the preferred size of panel to 300, 300
        this.panel.setPreferredSize(new Dimension(300, 300));

        //set the panel layout to flow layout, with alignment to Center
        this.panel.setLayout(new FlowLayout(FlowLayout.CENTER));

        //Set the Frame window size to 300, 300
        this.setSize(300, 300);

        //set the Frame layout to flow layout, with alignment to Center
        this.panel.setLayout(new FlowLayout(FlowLayout.CENTER));


        //Make the panel visible
        this.setVisible(true);

        //Loop to create 6 mass-boxes
        while(count < size){
        	//Create checkbox with count passed to show text as 0, 1, 2, 3, 4, 5
            JCheckBox checkbox = new JCheckBox(" " + count);

            //Set the background to a random color
            checkbox.setBackground(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

            //Add checkbox to panel
            panel.add(checkbox);

            //increate count
            count++;
        }//end while

        //add panel to the frame window
        this.add(this.panel);

        //call pack() method to pack all the GUI components
        this.pack();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        //old school crap
        //new ChecKApp_1(6);

        //better and more advanced way
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new CheckApp(24);
            }
        });
    }

}
```

Viel Freude liebe Programmierer...

Viele Grüße
Semox


----------



## 0x7F800000 (1. Jan 2009)

Also, es läuft, und weitere Fragen hast du nicht? gut... dann

Verbesserungsvorschläge:

-Random r wird nur lokal im Konstruktor gebraucht, es hat nichts in der liste der Member-variablen zu suchen, es ist ja keine eigenschaft deines Fensters
-bist du dir sicher, dass du "count" in Member-variblen brauchst? Möglich, aber schwer vorstellbar. 
-setVisible(true) sollte man immer gaaanz zuletzt aufrufen, ansonsten bleiben manchmal manche components ungezeichnet, und tauchen erst später auf, wenn man mit der maus drüberfährt
-"xyz=S; while(xyz<A){ ... xyz++; ...}" fleht einen fast an, durch ein for(xyz=S; xyz<A; xyz++){...} ersetzt zu werden.
-JFrames werden alle gewöhnlichen components nicht direkt hinzugefügt, die kommen alle auf das contentPane, also statt "this.add(this.panel); " sollte es "this.getContentPane().add(this.panel)" heißen.
-so wie du diese invokeLater geschichte anwendest, kommt es mir klein wenig suspekt vor. Aber dazu sag ich lieber nichts, ich kenn das irgendwie nur von applets, und was da los ist, weiß ich selber nicht so recht. :roll:

so, da hast du wieder was zu basteln


----------



## Tobias (1. Jan 2009)

das invokeLater() sieht doch gut aus?!


----------



## André Uhres (1. Jan 2009)

Andrey hat gesagt.:
			
		

> -so wie du diese invokeLater geschichte anwendest, kommt es mir klein wenig suspekt vor.
> Aber dazu sag ich lieber nichts...


...bevor ich diesen Thread gelesen habe :wink:
http://www.java-forum.org/de/viewtopic.php?p=479584#479584


----------



## 0x7F800000 (1. Jan 2009)

André Uhres hat gesagt.:
			
		

> ...bevor ich diesen Thread gelesen habe :wink:


den hab ich schonmal gelesen. Suspekt kam es mir deshalb vor, weil ich bei applets "nur" den Aufbau der GUI auf diese art und weise bewerkstellige (JApplet selbst exklusive) und bei fenstern den gesamten Konstruktor reinpacke (Aufbau vom Fenster inklusive). Hab mir das jetzt nochmal in der API nachgeguggt: tatsächlich, JApplet ist ja gar keine Swing-Komponente, sondern erbt direkt von applet. Aus dieser ecke kam die verwirrung. Sorry.


----------



## Semox (1. Jan 2009)

Hallo Andrey

Vielen Dank für die Verbesserungsvorschläge... Würde ich gerne ausprobieren, aber leider fehlt mir erheblich die Zeit das zu perfektionieren. Dafür nehme ich mir aber gerne Deine Tips zu Herzen und werde das in künftigen Programmen beachten.

Habe leider noch 5 fette Aufgaben aus 4 Lektionen zu bewältigen... Plus die Zeit für die Prüfungsvorbereitung nur 2 Wochen Zeit... Dabei darf ich keine Zeit mit Perfektionieren verlieren... (obwohl ich weiß Gott gern "guten" Coden schreiben möchte  )

Viele Grüße
Semox


----------

