View aus anderen Thread aktualisieren

Status
Nicht offen für weitere Antworten.

stefan.

Mitglied
Hallo,

ich habe eine View mit einer Table

View:

Code:
public class MessageView extends ViewPart {
private TableViewer viewer;
private MyList myList;

	public void createPartControl(Composite parent) {
		this.parent=parent;

		myList=new MyList();
		StaticClass.setMyList(myList);
		
		Composite tableComposite = new Composite(parent, SWT.NONE);
		TableColumnLayout tableColumnLayout = new TableColumnLayout();
		tableComposite.setLayout(tableColumnLayout);
		viewer = new TableViewer(tableComposite, SWT.MULTI|SWT.H_SCROLL|		SWT.V_SCROLL|SWT.FULL_SELECTION);

		// Spalte erzeugen
		TableViewerColumn viewermessageColumn = new TableViewerColumn(viewer, SWT.NONE);
		viewermessageColumn.getColumn().setText("Message");
		tableColumnLayout.setColumnData(viewermessageColumn.getColumn(), new ColumnWeightData(88,600,true));

		viewer.setContentProvider(new MessageContent...);
		
		viewer.setInput(myList);	
	}
}

MyList – Liste welche die Nachrichten enthält
Code:
public class MyList {
	private Vector<Message> messagelist = new Vector<Message>();
	private Set<IMessageListViewer> changeListeners = new HashSet<IMessageListViewer>();
	
	public void addMessage(Message message){
		messagelist.add(message);
		Iterator<IMessageListViewer> iterator = changeListeners.iterator();
		while (iterator.hasNext())
			((IMessageListViewer) iterator.next()).addMessage(message);
	}
	public void removeChangeListener(IMessageListViewer viewer) {
		changeListeners.remove(viewer);
	}

	public void addChangeListener(IMessageListViewer viewer) {
		changeListeners.add(viewer);
	}

zugehöriges List Interface: IMessageListViewer
Code:
public interface IMessageListViewer {
	
	public void addMessage(FixMessage message);
}
Nun habe ich einen 2. Thread welcher empfangene Nachrichten in der View darstellen soll:

Klasse welche Nachrichten empfängt:

Code:
public class MessageProvider implements IMessage {
	@Override
	public void newMessage(Message message) {
		//Message in Liste adden

		final Message a=message;
		getDisplay().asyncExec(new Runnable() {
			@Override
			public void run() {
				StaticClass.getMyList.addMessage(a);
	
			}
		}
	}
}

Da ich sonst eine Exception bekomme, weil der Viewer in einem anderen Thread läuft, muss ich die Liste über die asyncExec() Methode aktualisieren.

Die Liste bekomme ich (in der newMessage()) über eine statische Variable, nun habe ich da aber 2 Probleme:
1. werden die empfangenen Nachrichten-Objekte (mir unerklärlicherweise) beim empfangen neuer Nachrichten teilweise vom Inhalt verändert und 2. ist die Lösung alles andere als schön/elegant.

Deswegen nun die Frage, wie kann ich es besser machen , d.h. Wie komme ich aus dem 2. Thread in der Methode newMessage() an die Liste um neue Nachrichten anzufügen?

Danke für jeden Tipp!

PS: Es handelt sich um eine RCP Anwendung.
 

dzim

Top Contributor
Ähm... Ich bin auf dem Gebiet der Threads nicht so firm, aber ich denke, was du mal versuchen könntest, wäre der UIJob.
Ich hab mit dem immer hantiert, wenn ich irgendwo was auf einer GUI anpassen musste (sonst kam immer eine IllegalThreadAccessException oder so).

Versuchs einfach mal, schaden kann's jedenfalls nicht!
 

stefan.

Mitglied
Hallo dzim,

das mit den UIJob klingt interessant, werde ich mir auch nochmal näher anschauen aber auf dem ersten Blick scheint das die gleiche Wirkung wie getDisplay().asyncExec(new Runnable() {} zu haben !? Denn ohne asyncExec() bekomme ich die IllegalThread.. Exception ...

Ich suche zunächst nach einer Möglichkeit die Liste global? in der RCP Anwendung ablegen zu können um dann von jedem Plugin aus darauf zuzugreifen. Evtl gibt es ja dafür einen ExtensionPoint? Bzw. wie wird das sonst gehandhabt ?
 
Zuletzt bearbeitet:

dzim

Top Contributor
k.A. Wildcard ist hier der crack! ,-)

Ich würde es aber vielleicht wirklich über einen eigenen ExtensionPint machen.
Dann müssen sich andere Plugins aber über den Extension Point als Listener registrieren. Das wär vielleicht das einfachste.

Aber da ich dein Problem noch nicht 100%ig verstanden habe, bin ich da vielleicht gerade noch nicht die große Hilfe.

Fakt ist: Wenn du PlugIn übergreifend arbeiten willst, wirst du um Extension Points nicht herum kommen, aus eigener Erfahrung weiß ich, das das zwar ein bisschen tricky ist, aber alles im Rahmen des Machbaren.
 

stefan.

Mitglied
Aber da ich dein Problem noch nicht 100%ig verstanden habe, bin ich da vielleicht gerade noch nicht die große Hilfe.

Was ist dir denn unklar? Kann es ja nochmal versuchen näher zu Beschreiben:

Ich benutze in einer View die JFace Komponente TableViewer. Diese soll Nachrichten welche über einen extra Thread empfangen werden darstellen. Bei neuen Nachrichten wird die newMessage() Methode aufgerufen, also muss ich von dieser Methode aus den TableViewer aktualiseren (Nachricht hinzufügen).
Dem TableViewer kann ich über setInput z.B. eine Liste mit Objekten übergeben die dargestellt werden. Wenn ich diese Liste aber in der View selber erzeuge, habe ich keine Referenz darauf. Somit benötige ich irgend eine Möglichkeit die Referenz der Liste global abzulegen um dann in der newMessage() auf die Referenz zuzugreifen und liste.addMessage() auszuführen.
 

Wildcard

Top Contributor
Beziehe dich immer auf das gleiche Modell (die gleiche Instanz). Kommt eine neue Message dann fügst du sie dem Parent hinzu, informierst die Listener das sich die Struktur des Parents geändert hat. Einer dieser Listener refreshed dann den Tree mit asyncExec.
Schau dir vielleicht mal EMF an. Damit bekommst du ein sehr mächtiges Datenmodell mit kompletem Notification Support und auf Wunsch auch Databinding das dir das ganze gehampel abnimmt.
 

stefan.

Mitglied
Hallo Wildcard, danke für deinen Tip!

Meinst du nach dem Observable-Prinzip, ich habe einen Beobachter, der bei einer neuen Nachricht informiert wird und dann addMessage macht ? Wobei ich den Beobachter ja auch irgendwie anmelden müsste und wieder Referenzen bräuchte .. und was meinst du mit Parent ? So richtig blick ich leider noch nicht durch :(

Hast du evtl ein Beispiel/Tutorial/Einführung in EMF ?
 

Wildcard

Top Contributor
Ahh, nicht Parent, habe mich verlesen, du hast einen TableViewer, keinen TreeViewer.
Trotzdem hast du wohl irgendeine Form der Datenstruktur die GUI unabhängig ist. Die wird verändert und benachrichtigt die Observer.
 

stefan.

Mitglied
Selbst wenn meine Datenstruktur zusätzlich als Observer arbeitet, weiss ich nicht wie ich mich am Observable registrieren soll, da mir dessen Referenz fehlt.

addmessage.png


Mein Problem ist:

Da ich die Viewer instanz nicht selbst erzeuge sondern RCP das für mich tut, weiss ich nicht wie ich auf diese zugreifen kann. Wenn ich die Instanz selbst erzeugen würde, könnte ich diese beispielsweise über get() bis zur gewünschten Stelle durchreichen. Also muss es doch in RCP eine Möglichkeit geben (zumindest innerhalb eines Plugins) Methoden anderer Klassen aufzurufen?
 

Wildcard

Top Contributor
Du kannst dir natürlich problemlos eine Referenz auf die View abolen (ist ein ganz normales Objekt), aber das Datenmodel sollte normalerweise eher ausserhalb der View verwaltet werden, die View ist dann nur ein 'View' ;) auf die Daten anstatt sie selbst zu erzeugen.
Angenommen du hättest so eine Art MessageProvider der alle Messages vorhält und an dem sich Observer registrieren können.
Deine View würde sich auf diesem Provider als Observer anmelden und informiert werden wenn es etwas neues gibt und der Thread wird vom Provider selbst gestartet um neue Nachrichten zu empfangen.
 

stefan.

Mitglied
Angenommen du hättest so eine Art MessageProvider der alle Messages vorhält und an dem sich Observer registrieren können.
Deine View würde sich auf diesem Provider als Observer anmelden und informiert werden wenn es etwas neues gibt und der Thread wird vom Provider selbst gestartet um neue Nachrichten zu empfangen.

Du meinst die View initiiert den MessageProvider und meldet sich zugleich bei diesem als Observer an. Der MessageProvider startet einen extra Thread welcher auf Nachrichten wartet? Das wäre zum einem weniger schön, da man dann von der View abhängig ist und zum anderen geht das in meinem Fall nicht, da der Thread von einem anderen Plugin initiiert wird.

addmessage2.png


Plugin.core stellt einen ExtensionPoint zur Verfügung mit einem Java-Attribut (Plugin.view erweitert diesen). Beim Aufbau der Verbindung erzeugt das core Plugin mittels
Java:
configurationElement.createExecutableExtension("class");
eine neue Instanz der Klasse welche Nachrichten empfängt.
Gibt es bei RCP keine Möglichkeit Objekte/Datenstrukturen global abzulegen ?

Und rein Interesse halber, wie kann ich mir ein View-Objekt holen, müsste ja irgendwie über die Workbench gehen ?
 

stefan.

Mitglied
Hallo Wildcard,

zunächst ersteinmal danke für den Tipp mit OSGi! Für die Messages habe ich nun den EventAdmin Service genommen, welcher genau auf die Aufgabe passt ;-)

Eine allgemeine Frage habe ich aber dennnoch:

Die Verbindungs-Logik (Aufbau, senden einer Nachricht etc..) habe ich in ein separates Plugin ausgelagert. Dieses Plugin exportiert einige Packages und in der (RCP) Oberfläche lege ich dann per klick auf Verbinden ein Objekt der Verbindungs-Logik an und rufe die start() Methode davon auf. Nun ist dies alles andere als 'unabhängig von der GUI', deswegen die Frage: Wie kann ich das besser Konzipieren? Wäre ein weiterer OSGi Service dafür geeignet, wovon sich die GUI eine Referenz holt?
 

Wildcard

Top Contributor
Die 'Verbindungslogik' exportiert einen OSGi Service (YourConnectionService) der dann zB eine login(Credentials) Methode hat.
OSGi Declarative Services bieten sich hervorragend dafür an.
 

stefan.

Mitglied
@Wildcard

habe es nun genauso gemacht wie du Vorgeschlagen hast und funktioniert auch sehr gut :toll:

Für den Verbindungsaufbau (und Abbau) benutze ich ein Command welches mit (je) einen Button verknüpft ist. Das command definiert einen defaultHandler womit ich in der execute() Methode die Verbindung aufbauen kann.

execute() im DefaultHandler startConnection:
Code:
public Object execute(ExecutionEvent event) throws ExecutionException {
	//... Service Referenz holen, start Connection() ...
}

Aber wie kann ich die Buttons connect/disconnect dynamsich enablen bzw. disablen? (Also connect nach erfolgreichem Verbindungsaufbau disablen, disconnect Button enablen).
Denn die isEnabled() Methode im Handler aktualisiert sich nur bei Fokus-Änderungen ?
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
A Overlay in View eines anderen Plug-Ins zeichnen Plattformprogrammierung 2
S RCP Nach erfolgreicher Erstellung der View, wie weitermachen? Plattformprogrammierung 1
G RCP Show View Command bestimmte View nicht erlauben Plattformprogrammierung 2
S RCP ActionBar Icon nur aktiv, wenn Selection in bestimmter View Plattformprogrammierung 6
M Plugin - Property Page - Get IResource in View Plattformprogrammierung 4
R Eclipse RCP Tabellen-View (Anfängerfrage) Plattformprogrammierung 3
L RCP Eigene View für EditorPart? Plattformprogrammierung 3
M RCP TableViewer schrumpft in View nach manueller Resize auf 1 Zeile Plattformprogrammierung 5
M EMF und Tabbed Properties View Plattformprogrammierung 4
Madlip RCP View austauschen/ändern Plattformprogrammierung 9
B RCP View aktualisieren bei Änderung 2. View Plattformprogrammierung 8
F RCP EMF View Plattformprogrammierung 13
K RCP View wird nicht angezeigt Plattformprogrammierung 2
L RCP Detached View beim Starten des RCPs? Plattformprogrammierung 3
F Tollbar Items disabled wenn View den Focus verliert Plattformprogrammierung 3
S RCP name einer view ändern Plattformprogrammierung 2
L RCP Help in eine View einbinden? Plattformprogrammierung 3
G RCP Menüpunkt Show View Plattformprogrammierung 7
G EMF -> Leere Elemente sollen in Property View nicht angezeigt werden Plattformprogrammierung 9
E eclipse RCP Properties View: ein Element aus Liste pro Zeile anzeigen Plattformprogrammierung 1
Z Eclipse RCP - UDP Strom in View anzeigen Plattformprogrammierung 4
L RCP Canvas in einer View? Plattformprogrammierung 4
lumo Eclipse + 'Could not create view' Plattformprogrammierung 5
L RCP View in einem Editor öffnen? Plattformprogrammierung 3
D Canvas auf View in Eclipse PlugIn Plattformprogrammierung 3
T RCP Menubar wird durch OLE-VIEW überschrieben Plattformprogrammierung 4
S Plugin: View beim Button-Klick austauschen Plattformprogrammierung 7
Saxony View als Image Plattformprogrammierung 2
S View Refreshen Plattformprogrammierung 2
T geladene Views / Event wenn View closed Plattformprogrammierung 4
S Steuerung View (Schließen erkennen/Hide anstatt Close) Plattformprogrammierung 2
S View speichern/laden beim schließen Plattformprogrammierung 14
L View schließen Plattformprogrammierung 7
L View nicht bekannt machen Plattformprogrammierung 4
lumo View aktivieren jedesmal wen.... Plattformprogrammierung 7
A View ansprechen Plattformprogrammierung 5
T GMF Property View Plattformprogrammierung 4
M Command in Toolbar aktiv wenn View nicht aktiv Plattformprogrammierung 2
C RCP: Veraenderungen innerhalb einer View per Extension?! Plattformprogrammierung 7
T JSVGCanvas in RCP View anzeigen Plattformprogrammierung 5
ARadauer Mehrere Gui Elemente in View Plattformprogrammierung 4
B RCP - Zugriff von View auf andere View Plattformprogrammierung 4
Saxony [Eclipse RCP] Von woanders View updaten Plattformprogrammierung 11
K Position einer Multiple View speichern Plattformprogrammierung 6
S RCP Anfängerfrage - Zusammenspiel View, Editor, Model Plattformprogrammierung 4
G View Daten übergabe. Plattformprogrammierung 4
N Nicht schließbare View? Plattformprogrammierung 7
C View updaten Teil 2 Plattformprogrammierung 2
B Eclipse RCP: View updaten Plattformprogrammierung 10
dzim Editor aus View öffnen - fehler: unbekannte Editor ID Plattformprogrammierung 11
J Editorfenster von View navigieren lassen? Plattformprogrammierung 5
T Aus einem View in das andere wecheln. Plattformprogrammierung 13
R SWT: nur eine Instanz einer View erlauben Plattformprogrammierung 5
F OSGi Applikation läuft einem Linux langsam, auf dem anderen normal Plattformprogrammierung 4
D Plugin - JUnit - Tests aus einem anderen Projekt ausführen Plattformprogrammierung 7
E eclipse RCP Anwendung programmatisch / aus einem anderen Programme starten? Plattformprogrammierung 8
M Problem beim Zugriff auf Klasse aus Fragment in einem anderen Plugin Plattformprogrammierung 3
S In einem Plugin main einer anderen Klasse aufrufen Plattformprogrammierung 18
H Thread beenden Plattformprogrammierung 14
S Eclipse UI blockiert - laengere Ablaeufe auf dem main-Thread..? Plattformprogrammierung 7

Ähnliche Java Themen


Oben