Methode setText() funktioniert nicht

Hallo,

ich habe in einem JFrame einen JDialog erzeugt, indem u.a. Labels platziert sind. Wenn ich in dem JDialog einen Button drücke, startet eine Berechnungsmethode. Diese Methode ist eine Schleife und mit jedem Schleifendurchlauf rufe ich setText()-Methoden auf, um die Label im JDialog zu „aktualisieren“. Die Labels sollen also den Fortschritt der Methodenausführung anzeigen.

Aber es passiert einfach gar nichts. Erst wenn die Methode fertig mit arbeiten ist werden die Label gesetzt.
Meine Frage ist daher: Warum funktionieren die setText-Methoden nicht bzw. nur unter bestimmten Umständen? Und wie kann ich das Problem lösen?

LG,
Infostudent.

hallo

also, dein problem ist nicht so leicht zu erklären bzw. zu lösen. ähnliche probleme hast du bei praktisch allen programmiersprachen.

im java gibt es einen eigenen thread, der für das zeichnen der gui sowie das verarbeiten der events (z.b. mouseevents) zuständig ist. dieser thread heisst swingthread. wenn du nun eine methode durch einen button-click startest, läuft diese methode im swingthread ab. wenn du eine schleife hast, dann ist der swingthread solange blockiert, solange die schleife läuft. dein setText funktioniert prima - im sinne, dass nach dem methodenaufruf der wert des labels tatsächlich deinen gesetzten wert hat. allerdings kann der swingthread die gui nicht neu zeichen, wesshalb du die änderung nicht siehst. erst ganz zum schluss wenn deine schleife beendet ist, kommt der swingthread wieder zum zug und kann die gui wieder aktualisieren. allerdings siehst du nun nur mehr den endwert des labels.

eine abhilfe ist gar nicht mal so einfach. zunächst einmal musst du deine schleife vom swingthread entkoppeln - also in einen eingenen thread auslagern. auf gui-elemente sollte eigentlich nur der swingthread zugreifen, deine setText-aufrufe müssen daher mit SwingUtilities.invokeLater aufgerufen werden (du übergibst damit dem swingthread ein runnable, dass der swingthread bei nächster gelegenheit ausführt). zu guter letzt musst du noch sicherstellen, dass der swingthread überhaupt zum zug kommt. die spezifikation der java-vm garantiert nämlich nicht, dass die threads „präemtiv“ ausgeführt werden. es kann also durchaus sein, dass deine schleife zwar in einem eigenen thread läuft, der scheduler der vm aber die gesammte rechenzeit diesem thread zuweist und daher der swingthread trotzdem nicht zum zug kommt und die gui erst wieder nicht aktualisieren kann. um auf der sicheren seite zu sein, musst du also in regelmässigen abständen ein Thread.sleep(1) in deine schleife einbauen. damit zwingst du deinen thread, die kontrolle abzugeben, damit der scheduler auf jeden fall auch andere threads ausführen kann. deine schleife wird dadurch allerdings etwas langsamer.

normalerweise sollte die java-vm unter windows schon präemptiv sein, d.h. auch ohne sleeps sollte die gui nun aktualisiert werden. garantie dafür gibt es aber keine. du musst etwas herumexperimentieren, ob und wie oft du das sleep brauchst, damit die gui zufriedenstellend läuft.

aber aufpassen: multithreaded zu programmieren setzt etwas an erfahrung voraus. schnell kann man sich verhaspeln und seine gui in einen threadlock bringen - die gui reagiert dann überhaupt nicht mehr und das programm muss zwangsbeendet werden.

lg
erwin

Hallo Erwin, vielen Dank für deine Antwort. Hatte nicht gewusst, dass es so kompliziert ist.

mfg,
Infostudent.

Hallo,

wie schon Erwin geschrieben hat, ist das Problem etwas umfangreicher.
Unter http://www.galileodesign.de/openbook/javainsel5/java… findest Du aber ein ganz gute Lösung.

Merke Dir einfach, dass Du längere Aufgabe immer in einem separaten Thread auslagerst. Mit invokeLater(…) kannst Du dann bestimmte Ergebnisse wieder in den EQT bringen.

Gruß,
Frank