Zugriff auf GUI über Thread

Hallo Java-Experten,

in einer Anwendung, die die Visualisierung von Daten über eine grafische Benutzeroberfläche übernimmt und Anwenderdaten einliest, möchte ich eine rechenintensivere Operation in einem Thread auslagern.

public class ValueThread extends Thread {

 int a = 0;

 public ValueThread() {
 }

 public void run() {
 while (true) {
 if (isInterrupted()) {
 break;
 }
 ++a;
 System.out.println(a);
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {}
 }
 }
}

Ich starte den Thread beim Drücken eines Buttons auf der Oberfläche. Im Editor sehe ich dann die Variable a auch wie gewünscht hochzählen.

Nun würde ich gern eine Berechnung in dem Thread ausführen lassen. Dazu benötigt der Thread aber Informationen aus der Fensterklasse und muss das Ergebnis auch dort zurückgeben, damit ich es beispielsweise in einem Label anzeigen lassen kann.

Wie realisiert man dies in Java?

Gruß

Michael

hallo

ein paar kleine tipps:

  • eine referenz auf das gui-objekt in einem statischen feld hinterlegen (kann ruhig private sein - ist besser so)
  • zusätzlich eine öffentliche statische methode in die selbe klasse, die den zugriff auf deine informationen regelt (also eine public static getxxx-methode)
  • beides ist sinnvollerweise in deiner gui-klasse direkt angesiedelt - einfach weil es leichter wartbar ist

also z.b.

public class GUI extends JFrame() {
// hier der richtige gui-code...

// static field mit instanz auf das aktuelle objekt
// wird z.b. vom konstruktor befüllt!
private static GUI instance = null ;

// angenommen, das gui hat irgendwo ein property "menge",
// dann hat diese methode
public static int getMenge() {
 return instance.getMenge() ;
}
}

dein thread kann nun über

GUI.getMenge() ;

jederzeit auf den aktuellen Wert von „menge“ zugreifen, ohne die Instanz selber kennen zu müssen.

das übergeben von werten an die gui ist da schon etwas problematischer. nur der swingthread sollte direkt auf gui-elemente zugreifen, da es sonst zu massiven problemen kommen kann. der harmloseste effekt ist dabei, dass die änderungen an den gui-elementen erst gezeichnet werden, wenn der thread schon längst fertig ist.

du musst daher dem swingthread sagen, was er zu tun hat. das geht über die SwingUtilities.invokeLater-Methode. die bekommt ein runnable-objekt mit ähnlich wie ein thread). dieses runnable-objekt wird ausgeführt, sobald der swingthread zeit dafür hat. rennt dein thread also in einer endlosschleife, kann es sein, dass andere threads erst wieder keine rechenzeit bekommen, wenn du keine sleeps einbaust!

so kann das z.b. aussehen:

// wieder im kontext der obigen GUI-Klasse:

public static void setWert(int neuerWert) {
 Runnable doIt = new Runnable() {
 public void run () {
 instance.setWert(neuerWert);
 }
 }
 SwingUtilities.invokeLater(doIt);
}

es gibt sicher noch „schönere“ möglichkeiten, sowas zu erledigen. das ganze ist auch nur beispielcode, der so auf die schnelle hingeschrieben wurde, ohne gross nachzudenken. aber als ansatz reicht es meiner meinung nach völlig.

ach ja, wenn du massiv gebrauch von threads machst, musst du entsprechend noch alles synchronisieren. bei einem einzigen hintergrundthread kann man sich das sparen.

lg
erwin

Hallo Erwin,

das hat mir bereits sehr viel weiter geholfen.
Vielen Dank!

Gruß

Michael