# Button Funktion zuweisen in WindowBuilder



## LeoKalo (28. Okt 2019)

Hallo zusammen,
ich muss ein Programm für eine Losziehung schreiben, die dann mit einer GUI genutzt werden kann.
Den Code (inkl. kleiner Verzögerung um die Spannung zu erhöhen) habe ich relativ schnell fertig bekommen.
Der ist bestimmt nicht der beste aber er funktioniert.

```
package test;

public class Lelol {
            
    
        

    public static void main(String[] args) {
        // TODO Auto-generated method stub
    
        int countdown = 3;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(countdown);
        countdown = 2;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(countdown);
        countdown = 1;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(countdown);
        countdown = 0;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(countdown);
            

    
    
String[]names;
names = new String [9];

names[0] = "Leon" ;
names[1] = "Leon" ;
names[2] = "Leon" ;
names[3] = "Guido2" ;
names[4] = "Phillip2";
names[5] = "Svenja2" ;
names[6] = "lelq";
names[7] = "Name1";
names[8] = "Name2";

int num = (int) (Math.random()*9);
System.out.println(""+names[num]);
    }



    }
```



Diesen Code wollte ich jetzt mit Windowbuilder über einen einfachen Button ausgeben lassen.
Konkret also:
1. Klick auf den Button
2. Ausgabe Countdown
3. Ausgabe des zufälligen Namens

Ich habe mir dazu zahlreiche Tutorials angeschaut, aber ich habe in dem Drop-Down-Menü nach dem Rechtsclick im Design-Fenster die Option _addActionListener_ nicht.
Auch wenn ich versuche das manuell in den Code zu schreiben, klappt das nicht (import und implement habe ich auch versucht).
Leider bin ich absoluter Anfänger (hab mir vor einer Woche das erste mal Eclipse gedownloadet) und blicke deswegen leider garnicht durch viele Tutorials durch. Oft geht es zudem in Foren um viel komplexere Sachen. Eigentlich sollte mein Anwendungsfall ja sehr einfach sein.
Hat einer von Euch eine Idee warum ich bei mir mit Rechtsclick die Option nicht finde oder wie ich das umgehen kann?
Vielen Dank für Eure Hilfe!


----------



## mihe7 (28. Okt 2019)

LeoKalo hat gesagt.:


> Hat einer von Euch eine Idee warum ich bei mir mit Rechtsclick die Option nicht finde


Keine Ahnung (verwende das Ding nicht), aber wenn ich es richtig sehe: Rechtsklick auf den Button -> Add event handler -> action -> actionPerformed.


----------



## LeoKalo (28. Okt 2019)

mihe7 hat gesagt.:


> Keine Ahnung (verwende das Ding nicht), aber wenn ich es richtig sehe: Rechtsklick auf den Button -> Add event handler -> action -> actionPerformed.


Genau die Option finde ich in dem Untermenü nicht. Ich hab auch schon überlegt, ob ich evtl. die falsche Windowbuilder Version habe, aber jedes mal wird mir angezeigt, dass ich die neuste Version und alle Add-Ons habe.


----------



## mihe7 (28. Okt 2019)

Evtl. funkionierts über die Properties: https://help.eclipse.org/kepler/index.jsp?topic=/org.eclipse.wb.doc.user/html/index.html


----------



## LeoKalo (28. Okt 2019)

mihe7 hat gesagt.:


> Evtl. funkionierts über die Properties: https://help.eclipse.org/kepler/index.jsp?topic=/org.eclipse.wb.doc.user/html/index.html


Da hab ich auch mal geschaut, aber mit meinem sehr begrenztem Wissen leider nichts gefunden. Aber wenn du da eine Idee hast wo ich was finde wäre ich sehr dankbar! Oder hast du noch eine andere Idee wie ich den Code über einen Button initialisiert bekomme und das Ergebnis ausgegeben bekomme?


----------



## Robat (28. Okt 2019)

Warum es diese Option nicht gibt, kann ich dir nicht sagen. Du solltest aber - mMn - sowieso lieber gleich lernen GUIs von Hand zu schreiben. Dein Vorhaben klingt jetzt nicht wirklich kompliziert - da bist du bestimmt schneller dran es eben per Hand zu schreiben - ohne GUI Builder.

Gleich mal vorab: Du solltest dich nebenbei mit Threads beschäftigen. Wenn du die GUI hast und den Code so ausführst wie er ist, wirst du wohl nicht das sehen, was du vielleicht erwartest.


----------



## LeoKalo (28. Okt 2019)

Robat hat gesagt.:


> Warum es diese Option nicht gibt, kann ich dir nicht sagen. Du solltest aber - mMn - sowieso lieber gleich lernen GUIs von Hand zu schreiben. Dein Vorhaben klingt jetzt nicht wirklich kompliziert - da bist du bestimmt schneller dran es eben per Hand zu schreiben - ohne GUI Builder.
> 
> Gleich mal vorab: Du solltest dich nebenbei mit Threads beschäftigen. Wenn du die GUI hast und den Code so ausführst wie er ist, wirst du wohl nicht das sehen, was du vielleicht erwartest.


ja das mit dem von Hand schreiben hab ich auch versucht, erstmal mit einem deutlich einfacheren Beispiel, allerdings bin ich da schon nicht weitergekommen, da ich addAction auch nicht im Code anfügen konnte.
Ich hab hier auch schon im Forum mal gesucht, allerdings hab ich wenig geholfen, das mir wirklich weitergeholfen hat (bei diesem Problem). Hast du eine etwas konkretere Empfehlung wo ich da nachlesen kann? dann würde ich das natürlich machen!


----------



## Robat (28. Okt 2019)

Naja letztendlich gibt es genügend Material zu GUI Programmierung im Netz. Woran scheitert es denn genau? Was hast du denn versucht? 
Zeig deine bisherigen Versuche / Fragen mal .. dann wird das ganze etwas konkreter.


----------



## LeoKalo (28. Okt 2019)

Robat hat gesagt.:


> Naja letztendlich gibt es genügend Material zu GUI Programmierung im Netz. Woran scheitert es denn genau? Was hast du denn versucht?
> Zeig deine bisherigen Versuche / Fragen mal .. dann wird das ganze etwas konkreter.


ok also ich habe mehrere unter anderem allgemeine Fragen. Sorry wenn die Antworten dafür schon irgendwo stehen, könnt auch gerne darauf verweisen.
1. Inwiefern muss ich (meinen) Code umschreiben, wenn ich aus einer normalen Umgebung in eine GUI übergehe?
2. Kann ich einfach einen Button schreiben, der meinen normalen Java Code initialisiert? 
2.1 Ich hatte mir dann gedacht, es gäbe eine Funktion mit der ich dann einfach das, was bei println ausgegeben werden soll über ein Fenster in der GUI oder über ein Ausgabefeld ausgeben lasse. Das geht anscheinend nicht so einfach, wenn ich deine Posts lese oder etwa doch?


----------



## Robat (29. Okt 2019)

Da scheinen bei dir noch recht viele Baustellen offen zu sein. Normalerweise sollte man zu dem Zeitpunkt noch nichts mit grafischen Elementen machen, aber scheinbar ist das deine Aufgabe (?). Also mal Schritt für Schritt.

Dein Code solltest du ein ganzes Stück umstrukturieren. Dazu am Besten mal mit dem "Model View Controller"-Pattern (MVC) beschäftigen. Das zeigt dir u.A. auf wie du deinen Code so strukturierst, dass er von der Ausgabe unabhängig ist.

Was du bei deinem 2. Punkt mit "[..], der meinen normalen Java Code initialisiert" meinst weiß ich nicht so richtig. Es klingt erstmal falsch. Dein Button initialisiert keinen Java Code sondern teilt deiner Logik mit, dass jetzt eine neue Ziehung stattfinden soll. Das geschieht über den Aufruf einer Methode. Diese Methode gibt dann entsprechend Daten zurück, die du darstellen kannst. 

Zu deinem letzten Punkt: Die Ausgabe auf der GUI an sich ist auch trivial. Das machst du über `Label#setText(String)` (zB). Es geht aber eher darum, dass du nicht einfach mittels `Thread#sleep` den aktuellen Thread schlafen legen kannst, weil sonst deine GUI einfriert. Du musst den Counter in einen separaten Thread auslagern, der GUI sagen dass sie sich updaten soll, den Thread für x ms schlafen legen, dann wieder die GUI updaten, ... bis der Countdown fertig ist. Daher die Anregung: mit Threads beschäftigen. Hier könnte zB `javax.swing.Timer` interessant sein.

Meiner Meinung nach solltest du dich aber erstmal mit MVC beschäftigen und den Countdown erstmal weglassen, bis das Programm grundlegend steht. Das könnte sonst alles etwas überfordernd sein.


----------



## LeoKalo (29. Okt 2019)

Robat hat gesagt.:


> Da scheinen bei dir noch recht viele Baustellen offen zu sein. Normalerweise sollte man zu dem Zeitpunkt noch nichts mit grafischen Elementen machen, aber scheinbar ist das deine Aufgabe (?). Also mal Schritt für Schritt.
> 
> Dein Code solltest du ein ganzes Stück umstrukturieren. Dazu am Besten mal mit dem "Model View Controller"-Pattern (MVC) beschäftigen. Das zeigt dir u.A. auf wie du deinen Code so strukturierst, dass er von der Ausgabe unabhängig ist.
> 
> ...



Ja mir wurde erst gesagt, dass ich nur den Code schreiben soll, was ja kein Problem war. Das mit der GUI hatte ich auch erst nicht auf dem Schirm.
Aber vielen vielen Dank für Empfehlungen! Damit werde ich mich mal auseinandersetzen und es nochmal versuchen! 
Ich melde mich dann nochmal wenn es geklappt hat, oder ich eben wieder am verzweifeln bin!


----------



## Robat (29. Okt 2019)

Klaro. Wenns Fragen gibt einfach melden


----------



## LeoKalo (30. Okt 2019)

Hallo zusammen,
ich habe jetzt nochmal etwas rumprobiert, und habe jetzt den actionlistener gefunden.
Zudem habe ich meinen Losungscode minimiert um Fehler zu vermeiden.
Ich weiß jetzt auch, dass ich mir mit `println` keine Sachen im Windowbuilder anzeigen lassen kann.
Mit Threads habe ich mich mal auseinandergesetzt, allerdings habe ich nicht verstanden, warum das für meinen Anwendungsfall notwendig sein sollte. Wenn ich das richtig verstanden habe, sind Threads doch dafür da, um verschiedene Dinge gleichzeitig auszuführen. Das ist eigentlich nirgends nötig bei mir (kann da aber natürlich auch komplett falsch liegen).
So jetzt hänge ich in der folgenden noch einfacheren Situation:
Ich habe ein GUI Layout:

```
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JButton;
import java.awt.Font;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JTextField;

public class Losung1 {

    private JFrame frame;
    private JTextField textField;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Losung1 window = new Losung1();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public Losung1() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);
        
        JButton btnStartDerLosung = new JButton("Start der Losung");
        btnStartDerLosung.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            }
        });
        btnStartDerLosung.setBounds(154, 51, 119, 57);
        frame.getContentPane().add(btnStartDerLosung);
        
        textField = new JTextField();
        textField.setBounds(154, 174, 119, 20);
        frame.getContentPane().add(textField);
        textField.setColumns(10);
    }
}
```
So sollte später das Programm aussehen wenn möglich (wäre aber auch nicht schlimm wenn es anders aussieht, hauptsache es funktioniert) -  Das Textfeld sollte dann den Gewinner der Losung zeigen
2. Die Funktion die ich nun in die GUI implementieren will sollte ein äquivalentes Ergebnis zu diesem Code liefern:

```
package test;

public class Lelol {
    
String[]names;
names = new String [9];

names[0] = "Leon1" ;
names[1] = "Leon2" ;
names[2] = "Leon" ;
names[3] = "Guido2" ;
names[4] = "Phillip2";
names[5] = "Svenja2" ;
names[6] = "lelq";
names[7] = "Name1";
names[8] = "Name2";

int num = (int) (Math.random()*9);
System.out.println(""+names[num]);
    }



    }
```
Jetzt muss ich nur noch rausfinden, wie ich das umschreibe, damit ich damit in der GUI arbeiten kann.
Hat dafür jemand Literatur oder sogar (wäre noch viel besser) konkrete Tipps?
Sorry, dass es so lang geworden ist!


----------



## mihe7 (30. Okt 2019)

LeoKalo hat gesagt.:


> Wenn ich das richtig verstanden habe, sind Threads doch dafür da, um verschiedene Dinge gleichzeitig auszuführen. Das ist eigentlich nirgends nötig bei mir (kann da aber natürlich auch komplett falsch liegen).


Du liegst falsch  Es gibt einen Thread, den sog. Event Dispatch Thread (EDT), der sich um die GUI kümmert. Dazu gehören z. B. Mausbewegungen, die ja unabhängig von Deiner Anwendung ablaufen aber auch das Zeichnen der Oberfläche usw. Konkret gibt es einen Queue, die (sagen wir mal) Ereignisse speichert und der EDT arbeitet die Queue nacheinander ab. 

Wenn Dein Programm startet, befindet es sich im main-Thread und mit `EventQueue.invokeLater` legst Du das angegebene Runnable in die Event Queue, die im EDT abgearbeitet wird. Der Code Deines Runnables wird also im EDT ausgeführt (wie auch das Zeichnen der GUI etc.)

Wenn Du auf einen Button klickst, wird der Code in der actionPerformed-Methode ebenfalls im EDT ausgeführt. Machst Du dort ein einfaches Thread.sleep() blockierst Du den EDT und Deine Änderungen am UI können nicht neu gezeichnet werden. Folglich musst Du derlei Dinge in einen anderen Thread auslagern.


----------



## LeoKalo (30. Okt 2019)

mihe7 hat gesagt.:


> Du liegst falsch  Es gibt einen Thread, den sog. Event Dispatch Thread (EDT), der sich um die GUI kümmert. Dazu gehören z. B. Mausbewegungen, die ja unabhängig von Deiner Anwendung ablaufen aber auch das Zeichnen der Oberfläche usw. Konkret gibt es einen Queue, die (sagen wir mal) Ereignisse speichert und der EDT arbeitet die Queue nacheinander ab.
> 
> Wenn Dein Programm startet, befindet es sich im main-Thread und mit `EventQueue.invokeLater` legst Du das angegebene Runnable in die Event Queue, die im EDT abgearbeitet wird. Der Code Deines Runnables wird also im EDT ausgeführt (wie auch das Zeichnen der GUI etc.)
> 
> Wenn Du auf einen Button klickst, wird der Code in der actionPerformed-Methode ebenfalls im EDT ausgeführt. Machst Du dort ein einfaches Thread.sleep() blockierst Du den EDT und Deine Änderungen am UI können nicht neu gezeichnet werden. Folglich musst Du derlei Dinge in einen anderen Thread auslagern.


Ah ok ja das hab ich verstanden.
Was mich nur wundert, dass in zahlreichen Tutorials zu dem Thema (zb in dem hier: 



) sowas nicht gemacht wurde. Warum funktioniert das bei seiner Anwendung ohne Threads aber bei meiner nicht?


----------



## Robat (30. Okt 2019)

Hab jetzt nur kurz durchgeklickt aber er benutzt ja auch keine `Thread.sleep` , wenn ich das richtig gesehen habe.


----------



## LeoKalo (30. Okt 2019)

Robat hat gesagt.:


> Hab jetzt nur kurz durchgeklickt aber er benutzt ja auch keine `Thread.sleep` , wenn ich das richtig gesehen habe.


Aber das mach ich doch auch nicht oder? bzw brauche ich das ja nicht


----------



## LeoKalo (30. Okt 2019)

Robat hat gesagt.:


> Hab jetzt nur kurz durchgeklickt aber er benutzt ja auch keine `Thread.sleep` , wenn ich das richtig gesehen habe.


in dem neuen kürzeren Code ist der Countdown der`thread.sleep` beinhaltet nicht mehr drin falls du das übersehen hast


----------



## Robat (30. Okt 2019)

Den hab ich mir ehrlich gesagt gar nicht angeschaut weil ich nicht davon ausgegangen bin, dass du dein Vorhaben dahingehend änderst. Wenn du nirgends `Thread.sleep` nutzt brauchst du dich auch mit dem Thread Thema (erstmal) nicht beschäftigen.
Essentiell ist es für die Programmierung natürlich trotzdem.


----------



## LeoKalo (30. Okt 2019)

Robat hat gesagt.:


> Den hab ich mir ehrlich gesagt gar nicht angeschaut weil ich nicht davon ausgegangen bin, dass du dein Vorhaben dahingehend änderst. Wenn du nirgends `Thread.sleep` nutzt brauchst du dich auch mit dem Thread Thema (erstmal) nicht beschäftigen.
> Essentiell ist es für die Programmierung natürlich trotzdem.


Achso ja ich habe mittlerweile leider etwas Zeitdruck, deswegen habe ich erstmal das Projekt schlanker gemacht. Auch um Konkretere Fragen stellen zu können.
Dass das Thema an sich sehr wichtig ist, habe ich auch gemerkt und wenn ich mehr Zeit hätte würde ich mich aufjedenfall eingehend damit beschäftigen! Aber sowas kann man sich ja leider nicht immer aussuchen


----------



## Robat (30. Okt 2019)

Okay dann mal zurück zu deinem Post.
Du hast schon den ActionListener entdeckt über den du steuern kannst, was beim Button-Druck passieren soll. Bisher hat dein Programm einfach nur einen Namen auf der Konsole ausgegeben. Du willst diesen Namen nun in deiner GUI anzeigen lassen.
Das ist an sich nicht so schwer. Du brauchst dazu einen JButton und ein JLabel. (Du hast momentan ein jTextField .. das würde auch gehen ist aber eher für Texteingaben gedacht).
In der `actionPerformed(ActionEvent)` Methode musst du jetzt genau das machen, was du auch zuvor gemacht hast.

```
- Array mit Namen definieren
- zufällige Zahl ziehen
- Namen aus dem Array holen
- Anzeigen
```
Letzteres machst du über die Methode `JLabel#setText(String)`

Edit: Später würde man das ganze natürlich etwas eleganter lösen. Aber für die ersten Berührungspunkte mit GUI Anwendungen sollte das ausreichen.


----------



## LeoKalo (30. Okt 2019)

Robat hat gesagt.:


> Okay dann mal zurück zu deinem Post.
> Du hast schon den ActionListener entdeckt über den du steuern kannst, was beim Button-Druck passieren soll. Bisher hat dein Programm einfach nur einen Namen auf der Konsole ausgegeben. Du willst diesen Namen nun in deiner GUI anzeigen lassen.
> Das ist an sich nicht so schwer. Du brauchst dazu einen JButton und ein JLabel. (Du hast momentan ein jTextField .. das würde auch gehen ist aber eher für Texteingaben gedacht).
> In der `actionPerformed(ActionEvent)` Methode musst du jetzt genau das machen, was du auch zuvor gemacht hast.
> ...


Ah genau danke! Ich habe leider erst heute Abend wieder Zugriff auf den Code, aber dann probier ich das direkt mal und berichte dann danke!


----------



## LeoKalo (31. Okt 2019)

Robat hat gesagt.:


> Okay dann mal zurück zu deinem Post.
> Du hast schon den ActionListener entdeckt über den du steuern kannst, was beim Button-Druck passieren soll. Bisher hat dein Programm einfach nur einen Namen auf der Konsole ausgegeben. Du willst diesen Namen nun in deiner GUI anzeigen lassen.
> Das ist an sich nicht so schwer. Du brauchst dazu einen JButton und ein JLabel. (Du hast momentan ein jTextField .. das würde auch gehen ist aber eher für Texteingaben gedacht).
> In der `actionPerformed(ActionEvent)` Methode musst du jetzt genau das machen, was du auch zuvor gemacht hast.
> ...


So ich habe die Sachen jetzt implementiert/geändert und heute morgen hat es dann geklappt!
Vielen Dank für Eure Hilfe ohne Euch hätte ich das nicht geschafft!


----------

