Etwas was nach jedem GUI 'click' ausgeführt wird

Bolic

Mitglied
Hallo Freunde,

an der Überschrift merkt ihr sicherlich schon, dass es mir schwer fällt das Problem zu benennen.
Gibt es etwas/einen Bereich wo ich Befehle reinschreiben kann, die nach jeder GUI-Aktion ausgeführt werden?
Mit GUI-Aktionen meine ich überwiegend die Betätigung eines Buttons.

Ich möchte also nach jedem Buttonklick Methoden ausführen können.

Nun stellt ihr euch die Frage, warum ich nicht einfach ans Ende des Actionlisteners die Methoden dran packen kann/will:

Es handelt sich um ein rundenbasierendes Spiel. Nach jedem Klick von mir wird überprüft, ob ich noch "Klicks" für diese Runde übrig habe. Ist das nicht der Fall wird die Methode
Code:
letKiPlay()
ausgeführt. In dieser Methode wird zwei mal
Code:
Thread.sleep(int)
aufgerufen, damit nicht alle Sachen direkt geschehen, sondern dass es so aussieht, als ob die Ki wirklich spielt. Problem ist dabei, dass ich die gesamte Zeit einfach warte, WÄHREND der Button gedrückt bleibt (ist optisch eingedrückt), und am Ende es dann doch so ist, dass alles gleichzeitig dargestellt wird.

Meine Idee ist es also nun, diese Methode nicht mehr im Button aufzurufen sondern wo anderes. Nur wo?


Ich hoffe ich konnte das Problem halbwegs klar darstellen.

Danke für eure Mühen

Greetz
 
Dein Problem hat nichts mit einem ActionListener und Reaktion auf Button klicks zu tun, sondern mit Threads. Die musst das Rechnen und Schlafen der KI in einen eigenen Thread auslagern und die GUI nach und nach aktualisieren.
 
Hey,

vielen Dank für die Tipps. Habs nun auch so umsetzen können, dass es funktioniert.

Habe aber noch ein paar Fragen ehe ich die Lösung präsentiere 😉

1) Anhand des Szenarios von dem oberen Post, gibt es eine elengantere Weise "zu warten"? Mir scheint es, dass die Lösung mit dem Thread eher was hingebogen ist.

2) Ich gehe wie folgt vor.

Java:
package Roleplay;

public class Ki extends Thread {

	static Spieler kI;
	static Spieler spieler;
	static int upperRange = 100;
	static int midRange = 50;
	static int bottomRange = 15;
	static int random;
	
	@Override
	public void run(){
		try{
		    sleep(2000);
		}catch(InterruptedException e){
		    e.printStackTrace();
		}
		letKiPlayCast();
		try{
		    sleep(2000);
		}catch(InterruptedException e){
		    e.printStackTrace();
		}
		letKiPlayRandom();
		if(Main.spieler1Cast + Main.spieler1Random == 0){
			Check.switchAktivButton(0);
			Check.checkIfNextSpieler1();
			Check.checkIfEnd();
		}
	}
	
	public static void letKiPlayCast(){
		kI = Main.spielerpool.getSpieler(1);
		spieler = Main.spielerpool.getSpieler(0);
		
		random = (int) Math.random()*10;
		if(Main.spieler1Cast > 0){
			Main.spieler1Cast--;
			if(kI.getHp() > upperRange){
				spieler.setHp(kI.doDamageHit1(spieler.getHp(),spieler.getAp()));
			}
			else if(kI.getHp() < upperRange && kI.getHp() > midRange){
				if(random <= 5){
					spieler.setHp(kI.doDamageHit1(spieler.getHp(),spieler.getAp()));
				}
				else{
					spieler.setHp(kI.doDamageHit0(spieler.getHp(),spieler.getAp()));

				}
			}
			else if(kI.getHp() <= bottomRange){
				if(random <= 1){
					spieler.setHp(kI.doDamageHit1(spieler.getHp(),spieler.getAp()));
				}
				else{
					spieler.setHp(kI.doDamageHit0(spieler.getHp(),spieler.getAp()));

				}
			}
			Frame.textAreaLeftStats.setText("HP: "+spieler.getHp()+"\nAP: "+spieler.getAp());
			Frame.textAreaCombatLog.append("\n The Enemy hits you!");
		}
	}
	public static void letKiPlayRandom(){
		if(Main.spieler1Random > 0){
			Main.spieler1Random--;
			random = (int) Math.random()*10;
			if(random < 5){
				kI.doSelfBuff1();
				Frame.textAreaCombatLog.append("\n The Enemy heals his self!");
			}
			else if(random >= 5){
				kI.doDamageHit2(spieler.getHp(), spieler.getAp());
				Frame.textAreaCombatLog.append("\n The Enemy hits you!");
			}
			Frame.textAreaRightStats.setText("HP: "+kI.getHp()+"\nAP: "+kI.getAp());
		}
	}
}

Habe also die Klasse einfach umgeschrieben, sodass ich in der Main ein Objekt der klasse erstelle. Dann Obejekt.start() an der Stelle wo ich es eben haben will. Thread wird so wie gewollt ausgeführt.

ABER: ich kann den Thread nicht nochmal aufrufen. Sobald er einmal terminated ist, kann er aber per start nicht mehr aufgerufen werden. Meine Lösung ist dass ich einfach jedesmal ein neues Objekt nach dem terminaten erstelle..... Gibts da nicht was eleganteres, sinnvolleres? Finde leider keine Lösung
 
1) Anhand des Szenarios von dem oberen Post, gibt es eine elengantere Weise "zu warten"? Mir scheint es, dass die Lösung mit dem Thread eher was hingebogen ist.

Man könnte noch einen Timer verwenden und eine Aktion zum Zeitpunkt x ausführen lassen anstatt mit Thread.sleep zu warten. Ich finde hier spricht aber nichts gegen Thread.sleep.

2) Ich gehe wie folgt vor.

...

Habe also die Klasse einfach umgeschrieben, sodass ich in der Main ein Objekt der klasse erstelle. Dann Obejekt.start() an der Stelle wo ich es eben haben will. Thread wird so wie gewollt ausgeführt.

ABER: ich kann den Thread nicht nochmal aufrufen. Sobald er einmal terminated ist, kann er aber per start nicht mehr aufgerufen werden. Meine Lösung ist dass ich einfach jedesmal ein neues Objekt nach dem terminaten erstelle..... Gibts da nicht was eleganteres, sinnvolleres? Finde leider keine Lösung

Siehe Thread (Java Platform SE 6) . Ein einmal beendeter Thread kann nicht neugestartet werden. Ich kenne die Struktur/den Aufbau deines Programmes nicht, aber ich denke mal es wäre geschickter deine KI Runnable implementieren zu lassen und dann bei jedem Aufruf ein neues Thread-Objekt um dein Runnable zu bauen und das dann zu starten.

Ich muss aber dazu sagen, dass ich aus der Java EE Schiene komme und deshalb nichts mit Threads in ihrer Reinform zu tun habe. Also kA obs da ein Best Practice gibt.
 
Hm, sehe ich das richtig, dass der Unterschied zwischen
Code:
extends Thread
und
Code:
implements Runnable
nur der ist, dass wenn ich Runnable, also das Interface benutze, die Klasse noch von weiteren Klassen erben kann?

Sehe da sonst nun grad keinen Vorteil.

Grüße
 
Auch. Aber ein Runnable-Objekt kannst (bzw. musst) du in ein Thread-Objekt verpacken und musst es nicht jedes mal neu erzeugen.
 
Perfekt. Danke das hat mir alles sehr geholfen 😉

Wenns ein Admin ließt kann er ja den Thread verschieben. Gehört ja doch nicht ins GUI Forum 😉
 

Neue Themen


Zurück
Oben