# Methode warten lassen bis Button gedrückt wird



## babuschka (28. Dez 2011)

Hallo,
ich bin dabei ein Kartenspiel zu programmieren.
Über die Konsole ist es schon spielbar.
Jetzt möchte ich es um eine grafische Oberfläche erweitern.
Die schon programmierte Input Methode wollte ich gerade ersetzten.
Dabei stellt sich folgendes Problem. Bis jetzt hat der Spielablauf (logik) die Methode Input aufgerufen.
Jetzt möchte ich das ganze über den ActionListener lösen.

Mein Problem ist folgendes:
das Programm bleibt in der "while (warte == true){} " schleife hängen,
obwohl bei dem drücken des Button "jb" warte == false ausgegeben wird
Woran kann das liegen? Wie kann ich das lösen?

Freu mich über jede Antwort. Schon einmal danke für die Mühe es durchzulesen.


```
static boolean warte = true;
...
	private class buttonhandler implements ActionListener {
		public void actionPerformed (ActionEvent e){
			if (e.getSource() == jb){
				warte = false;
				System.out.println(warte);   // false wird beim Button druck ausgegeben
			}
		}
	}
	public int input() {                                  // wird aufgerufen durch die Spiellogik
		while (warte == true){}                  // soll auf den ActionListener warten
		System.out.println(Integer.parseInt(tf.getText()));
		int output = Integer.parseInt(tf.getText());
		return output;
	}
```


----------



## Final_Striker (28. Dez 2011)

> while (warte == true){}



Das ist eine Endlosschleife und sie läuft wie der Name schon sagt endlos.


----------



## age (28. Dez 2011)

Du benutzt eine while-Schleife zum warten?
Das ist, sagen wir mal... ein Bisschen unkonventionell.

Benutz einen Thread und die Methode sleep dieser Klasse


----------



## babuschka (28. Dez 2011)

Danke. Das ist mir auch schon aufegefallen. (Ich weiß nur nicht wie ichs sonst lösen kann. Durch googlen bin ich auf wait() und notify() gestoßen, war mir aber zu kompliziert).

@age: wie würde so etwas aussehen, bzw. wie macht man das?


----------



## age (28. Dez 2011)

Start doch erst einmal einen Versuch mit deinen gegoogleten Ratschlägen, bevor du sagst, dass es Dir zu kompliziert ist?

Google doch mal nach Java Open Book und such nach Thread


----------



## babuschka (28. Dez 2011)

hab ich schon ein paar mal probiert. aber das sind doch abwechselden threads, oder? und der listener funktioniert immer und zwar parallel. (das syso(warte), wird ja ausgegeben)


----------



## bygones (28. Dez 2011)

wozu brauchst du ueberhaupt deas while... ?

wenn dein button gedrueckt wurde, wird die methode aufgerufen... die muss ja vorher nicht "aktiv" sein.


----------



## age (28. Dez 2011)

Zuerst kommt mir da grad generell zu deinem Programm eine Frage:
Warum wird input aufgerufen und dann gewartet?
Warum ruft der ActionListener die Methode nicht einfach selbst auf?


```
private class buttonhandler implements ActionListener {
    
    public void actionPerformed (ActionEvent e){
        
        if (e.getSource() == jb){
            
            getObject().input(); //getter des Objekts der Hauptklasse
        
        }
  
    }

}

public int input() {   

    System.out.println(Integer.parseInt(tf.getText()));
    int output = Integer.parseInt(tf.getText());
    return output;

}
```

Oder:


```
private class buttonhandler implements ActionListener {
    
    public void actionPerformed (ActionEvent e){
        
        if (e.getSource() == jb){
            
            System.out.println(Integer.parseInt(tf.getText())); // Edit: tf eben auch wieder mit Getter...
            int output = Integer.parseInt(tf.getText());           
            return output;
        
        }
  
    }

}
```

Edit: Dazu benötigt dein Buttonhandler dann einen entsprechenden Konstruktor... hatte ich erst vergessen, sry.


----------



## babuschka (28. Dez 2011)

Dass mit dem aufrufen des inputs geschieht durch die Programmlogik (und ich möchte nicht das gesamte Programm umprogrammieren, wenn nicht notwendig),
 -> das ganze war davor über die Konsole zu bedienen
d.h. input über actionlistener aufzurufen geht, aber ist halt sehr aufwändig

das mit dem return statement im actionlister der void ist versteh ich nicht (wohin sollte das auch zurückgegeben werden)

Mein versuch an wait() und notify()


```
private class buttonhandler implements ActionListener {
		public void actionPerformed (ActionEvent e){
			if (e.getSource() == jb){
				notify();                  // soll wait sagen das es weiter darf
			}
		}
	}
	public int input() {
		try {
			wait();                            // soll stoppen bis notify kommt
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(Integer.parseInt(tf.getText()));
		int output = Integer.parseInt(tf.getText());
		return output;
	}
```


----------



## babuschka (28. Dez 2011)

ich benötige des weiteren den return wert im hauptprogramm (logik) und nicht im gui


----------



## age (28. Dez 2011)

Oh Verzeihung, ich hab nicht genau auf den Code geachtet.
Ich bin grad auf der Arbeit und mach das hier nur nebenbei 
Das return würde so natürlich nicht gehen, aber du würdest sicherlich auch ohne das return an den Wert kommen.

Hab grad keine Zeit mehr, so in einer halben Stunde kann ich wieder antworten, sry.


----------



## Landei (28. Dez 2011)

Listener sind der normale Weg, wie das "Hauptprogramm" an Werte der GUI kommt.


----------



## babuschka (28. Dez 2011)

kein problem. auf alle fälle vielen dank für die bereits erfolgte hilfe.

um mein problem übersichtlicher zu gestalten:


----------



## irgendjemand (28. Dez 2011)

ohne große weiter drumrumzureden

KONZEPTFEHLER !

deine main sollte dein "input" nicht aufrufen und dann dort in einem loop warten bis von außen ein flag geändert wirde ...

stattdessen wollte der EDT beim klick auf den button dein input() callen und das ergebnis an den nötigen caller returnen


----------



## babuschka (28. Dez 2011)

danke. aber was meinst du mit "callen"?


----------



## babuschka (28. Dez 2011)

ist callen = aufrufen?


----------



## Tobse (28. Dez 2011)

Wenn du es so machen willst: Ich habe das gliche Problm so gelöst (alleridngs auch mit wait()/notify()):

```
// Code aus dem MainFrame
// Wird aufgerufen, wenn über die GUI ein neues Projekt erstellt werden soll:
private void newProjectEntryActionPerformed(java.awt.event.ActionEvent evt) {                                                
    GUICache.N_PROJECT_FRAME.setVisible(true);
    final Thread t;
    Runnable r=new Runnable() {
        public void run() {
            while (GUICache.N_PROJECT_FRAME.available==0) {
                try {
                    Thread.sleep(100);
                } catch (Exception ex) {}
            }
            Project p=GUICache.N_PROJECT_FRAME.getCurrentProject();
            if (p==null) return;
            setProject(p);
        }
    };
    t=new Thread(r);
    t.start();
}
```


```
// Auszug aus der Klasse, deren instanz im oberen code GUICache.N_PROJECT_FRAME ist
    public void setVisible(boolean d) {
        if (d) {
            this.reset();
            this.currentProject=null;
        }
        super.setVisible(d);
    }
// Wird aufgerufen, wenn der Benutzer "erstellen "drückt
private void createBTActionPerformed(java.awt.event.ActionEvent evt) {                                         
    this.setVisible(false);
    //... Neues blankee erstellen
    this.available=1;
    try {
        notifyAll();
    } catch (Exception ex) {}
}
```

Funktioniert einwandfrei (62 - 190 Mhz CPU auslastung)


----------

