JDialog

Guten Tag

Ich habe einen eigenen JDialog gemacht und diesen Model gesetzt.

Ueber das Netzwerk kommt ein Bit das den Dialog öffnet, was auch funktioniert. Nur wenn ich das Bit wegnehme sollte der Dialog auch wieder verschwinden. Und dies tut es nicht mehr.

Modal muss er sein, wie also kann ich ihn wieder schliessen?

Dazu reicht eigentlich einfach eine setVisible(false) :wink:

Was heißt „Bit wegnehmen“?

Wenn Du von Netzwerk sprichst, heißt das Du liest einen InputStream über einen separaten Thread aus? Aus diesem Thread heraus rufst Du hoffentlich nicht setVisible(true) auf, so dass weiter gelesen werden kann?

Ja genau so ist das.

Nein nein mach ich nicht.

Nur mit dem SetModal wird ja die GUI eingefroren. Also kann sie ja auch nicht mehr über den Observer änderungen annehmen, was bedeutet ich bringe den Dialog nicht mehr weg…

Das mit dem setVisible hab ich probiert und geht so nicht. Wegen dem Empfangen der änderungen über Observer. Wenn ich aber dem Dialog in einem separaten Thread habe, sollte er auch nur diesem stoppen oder?

Eingefroren wird da nichts. Die GUI (vermutlich ein JFrame) ist nur nicht mehr für Anwender erreichbar.

Warum sollte Sie Änderungen über einen Observer (welchen Observer?) nicht mehr annehmen können?

Was heißt „hab ich probiert und geht so nicht“ ? Einen Dialog kann man nur wieder verschwinden lassen, indem man an diesem setVisible(false) oder dispose() aufruft.
So ganz verstehe ich nicht wie das bei Dir zusammenhängt. Woher kommt denn das „Signal“ den Dialog wieder auszublenden? Wie wird es empfängen? Wie wird darauf reagiert?

Jede 200ms wird meiner GUI über den Observer mitgeteillt die entsprechenden Daten anzurufen.

Wenn jetzt das bit model.getIORoboter2(1) gesetzt ist, wird der Dialog geöffnet, was auch funktioniert.

Ab diesem moment an wird über den Observer nie mehr etwas Empfangen, und somit setVisible(false) nie mehr aufgerufen…


				System.out.println("Guireload");

				if (model.getIORoboter2(1)) {
					sperrungOEE.sehen(true);
				} else {
					sperrungOEE.sehen(false);
				}

			}```

Heißt der Observer (ein java.util.Observer ?) ist verantwortlich für das Empfangen des „Signals“.
Und der Code sperrungOEE.sehen(true); wird in der update Methode aufgerufen? Was steckt denn hinter der Methode sehen?

Was mich an Deinem Konstrukt noch iritiert: Wozu der Observer, wenn ohnehin alle 200ms Daten abgerufen werden sollen? Warum kann die GUI oder deren Controller (falls so etwas existiert) nicht direkt alle 200ms die Daten abrufen?
Ein Observer dient dazu, um auf ein Ereignis zu reagieren, wenn es eintritt. Das ständige Pollen wiederspricht der Intention eines Observers.

[QUOTE=_Michael;28871]Heißt der Observer (ein java.util.Observer ?) ist verantwortlich für das Empfangen des „Signals“.
Und der Code sperrungOEE.sehen(true); wird in der update Methode aufgerufen? Was steckt denn hinter der Methode sehen?[/QUOTE]

Ja es ist der java.util.Observer

Er ist nicht wirklich verantwortlich, sondern sagt einfach der GUI holt euch eure Daten. Ich finde das aktualisieren geht so einfach weil ich über den Observer, ich könnte es auch in jedem Panel einzeln machen…

Der Observer reagiert in dem Sinne ja auf einen Event, der halt zyklisch alle 200ms aufgerufen wird.

Macht nichts anderes als in der JDialog klasse setVisible aufrufen.

Aber trotzdem kann ich mein JDialog nicht mit setVisible(false) zurücksetzen.

Meine Vermutung ist, dass Du das Observer-Pattern falsch rum angewendet hast.

Eigentlich sollte es so laufen:

Es gibt einen Thread, der am IO lauscht (also diesen beispielsweise alle 200ms pollt).

Dieser eine Thread is ein [JAPI]Observable[/JAPI] und die GUI-Komponenten (ins Besondere Dein Dialog) sind bei diesem als [JAPI]Observer[/JAPI] angemeldet.

Wenn der IO-Thread Daten zu verteilen hat gibt er diese an alle angemeldeten Observer weiter (update(this, data))

Die Observer müssen dann selbst raus kriegen, ob sie die übergebenen Daten weiter verarbeiten müssen/können.

bye
TT

Also hier schematisch mein Aufbau:

Die entsprechenden Panels die änderungen empfangen wollen melden sich so an den Observer an:

this.model.addObserver(this);

Im Model für die Visu läuft ein Timer der alle 200ms den lauschenden Panels sagt sie sollen sich Daten holen:

		TimerTask action = new TimerTask() {
			public void run() {
				setChanged();
				notifyObservers(TexteObserver.GUIRELOAD);
			}
		};
		Timer caretaker = new Timer();
		caretaker.schedule(action, 3000L, 250);
	}```

Was ich nicht mache ist über den Observer Daten schicken, die Panels holen sich das entsprechen im Model:

```			if (arg.equals(TexteObserver.GUIRELOAD)) {

				//System.out.println("Guireload");

				if (model.getIORoboter2(1)) {
					sperrungOEE.sehen(true);
				} else {
					sperrungOEE.sehen(false);
				}

			}```

Jedoch wird das Model nicht in einem separaten Thread aufgerufen das ist richtig, und werde ich mal versuchen zu ändern.

[QUOTE=headnut]Die entsprechenden Panels die änderungen empfangen wollen melden sich so an den Observer an:[/QUOTE]Wieso die Panels und nicht der Dialog?

[QUOTE=headnut;28893]Im Model für die Visu läuft ein Timer der alle 200ms den lauschenden Panels sagt sie sollen sich Daten holen:
[…]
Was ich nicht mache ist über den Observer Daten schicken,[/QUOTE]Warum nicht?
Genau dafür ist das Pattern doch da…

Und wie stellst Du sicher, dass jeder Observer (es gibt doch mehrere?) genau die Daten bekommt, die er braucht?

bye
TT

Einfach alles, sei es die Panel oder der Dialog.

[QUOTE=Timothy_Truckle;28899]Warum nicht?
Genau dafür ist das Pattern doch da…[/QUOTE]

Da hast du recht, aber ich habe ja in der View das Model als Instanz.

		if (model == o) {
			if (arg.equals(TexteObserver.FENSTERCHANGE)) {

				// Panel ändern
				CardLayout cl = (CardLayout) pnlCardLayout.getLayout();
				cl.show(pnlCardLayout, model.getAktivesFenster());
			}

			if (arg.equals(TexteObserver.GUIRELOAD)) {

				//System.out.println("Guireload");

				if (model.getIORoboter2(1)) {
					sperrungOEE.sehen(true);
				} else {
					sperrungOEE.sehen(false);
				}

			}
		}
	}```

Damit:

```		if (model == o) {
			if (arg.equals(TexteObserver.FENSTERCHANGE)) {```

Und im Model sind dann Getter für die entsprechenden Daten die von der View ausgelesen werden.

Ich habe mich damals mit Observer beschäftig und Beispiele gefunden die so aufgebaut waren, was soll daran nicht korrekt sein?

“Nicht korrekt” wäre vielleicht etwas hart, aber in diesem Fall nutzt Du den Observer nicht wirklich als solchen und es würde ein einfacher Listener ausreichen.

Egal, mittlerweile hast du ja meine Vermutung aus meinem ersten Post bestätigt: Da Du den Dialog innerhalb der update Methode sichtbar schaltest blockierst Du den Observer.

Aus reiner neugier, was wäre rein Performance mässig oder der Einfachheit halber der Unterschied?

Klar nutze ich den Observer nicht komplett aus, aber es ist wie ich finde eine extrem einfach Lösung als solches.

Jop werde heute abend die Geschichte umschreiben und den Observer in einen eigenen Thread schreiben.

Einen Unterschied gibt es nicht ein Listener ist ja ein Observer. In Deinem Fall wäre aber die Nutzung der Sun/Oracle Implementierung nicht notwendig und das Model müsste nicht Observable erweitern.

Einen eigenen Thread für den Observer brauchst Du nicht. Weiß auch nicht was das bringen soll - evtl. einfach nur unglücklich aus gedrückt.
Durch die Nutzung des Timers läuft der update Prozess bereits in einem separaten Thread. Du müsstes nur dafür sorgen, dass die Anzeige des Dialogs wieder im EDT (z.B. mittels SwingUtilities.invokeLater…) passiert. Aufgrund der Nutzung eines Timers wäre es grundsätzlich empfehlenswert darauf zu achten, dass Aktualisierungen an der GUI im EDT ausgeführt werden.

[QUOTE=headnut]Ich habe mich damals mit Observer beschäftig und Beispiele gefunden die so aufgebaut waren, was soll daran nicht korrekt sein?[/QUOTE]Ich möchte das nicht als falsch bezeichnen, aber als unzweckmäßig.

In Deinem Fall beispielsweise führt das dazu, dass Zeile 15 zwei mal hintereinander ausgeführt wird, ohne zwischendurch mal Zeile 17 auszuführen. Und was sagt die API über das wiederholte ausführen von setVisible()?

bye
TT

[QUOTE=Timothy_Truckle;28942]Ich möchte das nicht als falsch bezeichnen, aber als unzweckmäßig.

In Deinem Fall beispielsweise führt das dazu, dass Zeile 15 zwei mal hintereinander ausgeführt wird, ohne zwischendurch mal Zeile 17 auszuführen. Und was sagt die API über das wiederholte ausführen von setVisible()?

bye
TT[/QUOTE]

Das war auch der Sinn der Sache. Die Visualisierung ist solange gesperrt bis über das Netzwerk das Bit wieder weg ist.

Ich habe das nun in aller Ruhe getestet und es ist tatsächlich so, dass ich den Observer Thread lahmgelegt habe.

Nun hab ich es umgeschrieben und wollte Fragen on man dies so machen kann? Funktionieren tut es:


		// Oeffnet den Dialog
		if (model.getUmsch()) {
			if (!oeffnen) {
				new Thread(new Runnable() {

					@Override
					public void run() {
						setVisible(true);

					}
				}).start();

				oeffnen = true;
			}
		} else {
			oeffnen = false;
		}

		// Schliesst den Dialog
		if (!model.getUmsch()) {
			if (!schliessen) {
				setVisible(false);
				schliessen = true;
			} else {
				schliessen = false;
			}
		}
	}```

Kann man so machen, da Du den Timer nutzt würde es aber auch ausreichen das setVisible mittels invokeLater auf dem EDT auszuführen und man könnte auf das Erstellen eines zusätzlichen Threads verzichten.

Die Sache mit dem Timer und dem Pollen lässt mich aber nicht in Ruhe. Was passiert in der model.getUmsch()? Muss sich das Model beim Aufruf der Methode erst die Info irgendwoher holen?

model.getUmsch()

Ja genau so ist es. Die View hat in meinem Fall ein Model, dieses hat zugriff auf die Datenbank und die Netzwerkvebindungen. Diese Methode holt sich einfach das bit der “Netzwerkverwaltung” und gibt es der View weiter.