Sleep verhält sich unerwartet

Hallo ich habe folgendes Programm

maleRotenKreis

Thread.sleep(2000);

maleGelbenKreis

Ich erwarte das ich einen roten Kreis sehe 2 sek, und danach gelben. Das passiert aber nicht das Programm geht schlafen noch bevor ich rotenkreis sehe und nachdem auffwachen sehe ich dann gelben kreis. Wieso ist das so? Wie ich kann ich die Methode maleGelbenKreis() mit einer verzögerungen ausführen?

Ist maleGelbenKreis vielleicht versteckt? Sry, aber es darf aucgh mal gefeiert werden.

Edit: paintXXX kann quasi zufällig aufgerufen werden, arbeite mit % 2000 < 1000.

@CyborgBeta : manchmal, vielleicht immer, doch mit Antworten zurückhalten

ein ActionListener oder auch die paintComponent-Methode wird vom AWT-Event-Thread ausgeführt,
solange der aktiv ist, wird die GUI nicht neu gezeichnet, werden keine Eingabeereignisse verarbeitet usw.,
das ist meist auch ganz gut, denn ausgeführte Ändrungen in der GUI parallel zum GUI-Eigenleben kann böse Effekte haben

längerfristige Aktionen aus ActionListenern gehören in einen SwingWorker oder Thread,
paintComponent() sollte generell so kurz wie möglich sein, auch aufwendige Berechnungen/ Laden von Bildern von Festplatte zu vermeiden,
aktives Warten sowieso,

du brauchst einen Thread nebenher,

  • der zum Zeitpunkt X die Information ablegt, dass ein roter Kreis gemalt werden soll + repaint()-Aufruf,
  • dann im Thread 2 sec warten, die GUI lebt normal weiter, führt u.a. recht sofortig das Zeichnen des roten Kreises aus (falls keine Bugs)
  • dann legt der Thread die Information ab dass zwei Kreise gemalt werden sollen + repaint() -> die GUI zeichnet sich wieder komplett neu, diesmal beide Kreise

arbeite mal dieses Tutorial durch, da kommt alles wichtige sicher dran
http://forum.byte-welt.net/java-forum-erste-hilfe-vom-java-welt-kompetenz-zentrum/spiele-und-multimedia-programmierung/5049-quaxlis-spiele-tutorial.html

Ich vermute hier eher einen simplen Anfängerfehler : sleep() im EDT !

Zur Erklärung : wenn du etwas graphisches (GUI) machst läuft im Hintergrund der sog. EDT, der EventDispatchThread. Dieser Thread ist dafür verantwortlich das halt deine Zeichenbefehle auch wirklich umgesetzt werden und so auch überhaupt was auf deinem Monitor angezeigt wird. Viele machen nun den Fehler (gerade wenn man sich das erste Mal damit befasst) das man versucht das ganze Prozedural, also Zeile für Zeile, ablaufen zu lassen. Das funktioniert so aber in Java nicht.

Wenn du also dein Zeichen-Code irgendwo in einer paint()-Methode (bei Swing in paintComponent()) stehen hast wird diese Methode vom EDT aufgerufen und der Code der da drin steht ausgeführt.
Wenn dort jetzt sowas steht :

rot
sleep()
gelb

dann siehst du am Ende nur den gelben Kreis da der rote bereits schon wieder übermalt wurde, nämlich mit dem gelben den du danach gezeichnet hast.

Um also das gewünschte Ergebnis zu erhalten das erst ein roter Kreis und nach einer gewissen Zeit dann ein gelber Kreis gezeichnet wird musst dies auslagern, also in einen eigenen Thread außerhalb des EDT ziehen damit dieser seine Arbeit korrekt verrichten kann.

So ganz spontan würde ich das ungefähr so machen :

-paintXXX() mit einem flag-gesteuertem Code bestücken
-einen zweiten Thread nutzen der die Timeouts beinhaltet
-vom zweiten Thread die flags setzen und über repaint() den EDT zur Arbeit bewegen

Gerne kann ich dir das auch mal anhand von Beispiel-Code zeigen, da müsstest du mir aber doch etwas Zeit geben, so aus dem Stehgreif kann ichs dann doch nicht.

— EDIT

same-time-post …
kann man da nicht irgendwie mal so n Hinweis einbauen wie : “Es gibt neue Beiträge” bevor ein Post eingefügt wird ? Andere Foren schaffen das doch auch !

Also .paint(), kann/sollte durch repaint() angestoßen werden, wird „quasi zufällig“ aufgerufen und abgearbeitet. Was innerhalb der Methode geschieht, sollte nicht durch (t.)sleep() unterbrochen werden. Jetzt gibt’s zwei Möglichkeiten. 1. Zustandsvariablen, welche durch einen anderen Thread geändert werden und welcher ggf. auch repaint() aufruft, oder 2. ein Teil der Geschäftslogik steht in .paint(), aber keine Unterbrechung, also sctm und bedingte Anweisung (if-): sctm % 2000 < 1000. Aber das ist Geschäftslogik, welche schnell länger werden kann - so ist es auch bei Konstruktoren ohne Init.

Sen und slater, ich bin hier angemeldet, um andere zu helfen anzustoßen auch mal einen Link zu posten, mein Beitrag muss nicht wiss. korrekt sein. :wink: Ich bemühe mich.

Ich/wir haben lediglich „den Klassiker“ gebracht der halt leider von vielen GUI-Anfängern immer wieder gemacht wird. SlaterB hat es dabei sogar noch ne ganze Ecke ausführlicher erklärt als ich und auch auf einen guten Thread verwiesen.