aktualisierung des View im MVC-Pattern

Ralph-Uwe

Bekanntes Mitglied
Hallo,

ich habe das MVC-Pattern, so wie hier im Forum beschrieben ist, für mein Programm benutzt.

http://www.java-forum.org/allgemeines/91829-mvc.html

Leider habe ich ein Problem mit der aktualisieren des Viewer.
In meinem Programm wird eine Datenübertragung über sie Serielleschnittstelle durchgeführt.
Diese Datenübertragung brauch eine gewisse Zeit, bis sie fertig ist.
Ich habe das Verhalten durch ein Thread.Sleep(3000) simuliert.
Java:
    public void changeDirection() {
        Direction[] dir = Direction.values();
        wind.setDir(dir[(int) (Math.random() * 4)]);
        try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }

Das Ergebnis ist, dass durch klicken auf den Button "Change Direction"
sich der Programmablauf um 3 sec. verzögert.

Aber bevor die Pause entsteht, wird im Model "Wind" die neue Windrichtung eingetragen und
der Observer (Windviewer) über das update benachrichtigt.
Im Windviewer wird die Methode
Java:
   public void update(Observable arg0, Object arg1) {
        Wind wind = (Wind) arg1;
        direction.setText(wind.getDir().toString());
        speed.setText(String.valueOf(wind.getSpeed()));
        System.out.println("update");
    }

aufgerufen.
Auf der Console wird auch sofort die Nachricht "update" ausgegeben.
Aber die Anzeige in der GUI wird erst aktallisiert, nachdem die Pause von 3sec. beendet wurde.

Meine Frage ist jetzt, wie bekomme ich die GUI dazu ihre Anzeige sofort nach dem update zu aktualisieren?

Ich habe schon versucht in die Methode
Java:
public void update(Observable arg0, Object arg1)
ein notify() einzufügen. Das funktioniert zwar, aber dann bekomme ich eine Exception:
java.lang.IllegalMonitorStateException
 
Das "changeDirection" wird wohl durch einen Buttonklick oder so ausgeführt. Dann bewirkt das Thread.sleep, dass dort der Event-Dispatch-Thread (EDT) schläft - also der, der für Benutzereingaben, neuzeichnen und alles andere, was mit dem GUI zu tun hat, verantwortlich ist.

Pauschal würde man sagen: Da muss man einen neuen Thread einfügen. Wenn man Änderungen am Modell durch beliebige Threads erlauben will, muss man aber aufpassen, dass die Änderungen in der View (bei einem update) dann wieder vom EDT gemacht werden (denn NUR der darf solche Änderungen machen). Das würde man dann mit SwingUtilities.invokeLater machen.

Poste mal eine "changeDirection"-Methode, die etwas näher an dem ist, was tatsächlich verwendet wird. (Die spannende Frage ist aber auch: Was soll während der Pause passieren? Sophisticated wäre natürlich ein modaler Dialog...)
 
erstmal danke für Deine schnelle Antwort.

"Thread.sleep" steht in diesem Beispiel für eine Serielledatenübertragung mit einem
Drucker. Das heiß, dass der Thread im Originalprogramm nicht schläft sondern arbeitet.

Es werden Steuerzeichen an den Drucker übertragen, der diesen auffordert Zählerstände
zu übermitteln. Leider dauert das etwas ;(
Aus diesem Grund möchte in der GUI die Info ausgeben, dass gerade Daten übertragen werden
Ausgabe : "auf Statusabfrage warten...", damit der Benutzer weiß was los ist.

Leider erfolgt die Anzeige jetzt erst, wenn die Übertragung beendet ist.
(dann brauche ich sie eigendlich nicht mehr)

Die Idee mit einem weiteren Thread ist nicht schlecht.
Leider ist mir noch nicht ganz klar wie ich den einbauen müsste.

Interessant ist auf jeden Fall die Tatsache, dass die Anzeige sofort aktualisiert wird, wenn
in der update Methode ein notify() aufgerufen wird.
Vielleicht hast Du eine Idee, wie die dann entstehende Exception weg bekommt.

Gibt es eine Möglichkeit den Event-Dispatch-Thread (EDT) dazu zu bekommen die GUI
zu aktualisieren?

Edit: SwingUtilities.invokeLater(gui) steht im der Mainmethode
Java:
    public static void main(final String[] args) {
        Runnable gui = new Runnable() {
 
            @Override
            public void run() {
                new WindController();
            }
        };
        SwingUtilities.invokeLater(gui);
    }
 
Zuletzt bearbeitet:
Gibt es eine Möglichkeit den Event-Dispatch-Thread (EDT) dazu zu bekommen die GUI
zu aktualisieren?
Ja, deine Berechnung musst du wie gesagt in nem eigenen Thread ausführen.
Im einfachsten Fall reicht dir sowas wie:
Java:
new Thread(new Runnable() {
  public void run() {
    changeDirection();
  }
}).start();
 
ich danke Euch beiden für die gute Hilfe. :applaus: :toll:

Ich habe jetzt den gesamten zeitaufwendigen Teil ein einem eigenen Thread laufen.
Zwar mußte ich noch ein paar Anpassungen vornehmen, damit verhindert wird, dass
der Thread mehfach läuft, aber das war kein Problem.

Auf jeden Fall ist jetzt alles zu meiner Zufriedenheit. 😎
 
"Thread.sleep" steht in diesem Beispiel für eine Serielledatenübertragung mit einem
Drucker. Das heiß, dass der Thread im Originalprogramm nicht schläft sondern arbeitet.

Dazu noch kurz: Wir haben beide Unrecht 😀 Der Thread schläft nicht. Er arbeitet aber vermutlich auch nicht. Sondern er wartet vermutlich auf die Daten (je nachdem, wie dieses Lesen von der Schnittstelle genau abläuft -deswegen die Aufforderung, genaueren Code zu posten). Aber "Schlafen" und "Auf Eingaben warten" hat hier denselben Effekt, nämlich dass er sich nicht mehr ums GUI kümmern kann (deswegen ist ein Thread.sleep zum Testen auch OK).

Eigentlich müßten die setText-Aufrufe in der update-Methode jetzt wieder auf dem EDT gemacht werden.

Kannst dir auch mal die Klasse SwingWorker (Java Platform SE 6) ansehen, die ist für Dinge gemacht, die vom GUI aus gestartet werden und "im Hintergrund" laufen sollen.
 

Zurück
Oben