Lookup?! *Bahnhof*

Hallo zusammen,

versuche mich gerade etwas in Netbeans RCP einzuarbeiten und habe ein kleines Beispiel gebastelt:

Eine “Action” in Form eines Buttons in der Toolbar. Damit öffne ich mir einen JFileChoose, öffne eine Datei, lese diese und will danach ein daraus resultierendes Objekt in einer “TopComponent” (also z.b. in einem Editor-Fenster mit diversen JTextFields) anzeigen.

Dachte das kann nicht so schwer sein. Aber ich scheitere kläglich…

Ich nehme mal an ich habe das Konzept noch nicht verstanden. Alles was ich gelesen habe sagt: “Dazu nimmt man die Lookup API”.

Aber davon hab ich noch kein Plan. Ist die LookupAPI nur sowas wie ein Telefonbuch wo ich zuvor registrierte Objekte nachschlagen kann, oder ist das sowas wie eine Art Event-System: Ich schicke irgendwie auf der einen Seite was rein, und registrierte Listener hören darauf?

Hätte jetzt auf letzteres getippt.

Kann mir jemand ein einfaches Beispiel nennen wie ich eine Instanz des Objekts “Device” (ganz abstrakt, der Name tut nicht wirklich was zur Sache) von einer Action zu einer TopComponent kommuniziere?

Gruß
Alex

Hast du mal diesen Artikel gelesen: DevFaqLookup - NetBeans Wiki

Der scheint das ganz gut zu erkären.

Danke. Nach solche einer Erklärung hab ich bisher vergeblich gesucht.

*** Edit ***

Hmm, okay, so auf den ersten Blick klingt das alles logisch:

The simplest way to think of Lookup is that it is a Map where the keys are Class objects and the value for each key is an instance of the key class.

Openable o = selectedContext.lookup(Openable.class);
if (o != null) {
  o.open();
}```

Damit bekomme ich also das „Openable“ Objekt aus der „Map“.

Stellt sich noch die Frage: Wie bekomme ich da ein beliebiges Objekt in die „Map“ rein?

Ich hab’s mit

Lookups.singleton(someObject)

probiert, aber an einer anderen Stelle wo ich eigentlich einen Listener hierfür registriert habe passiert nix:

....
// Registrieren
    @Override
    public void componentOpened() {
        Lookup.Template tpl = new Lookup.Template(Device.class);
        result = Utilities.actionsGlobalContext().lookup(tpl);
        result.addLookupListener(this);
    }

// Deregistrieren
    @Override
    public void componentClosed() {
        result.removeLookupListener(this);
        result=null;
    }

......

// Darauf reagieren
    @Override
    public void resultChanged(LookupEvent lookupEvent) {
        Lookup.Result r = (Lookup.Result) lookupEvent.getSource();
        Collection c = r.allClasses();
        if (!c.isEmpty()) {
            Device o = (Device) c.iterator().next();
            manufacturerTextfield.setText(String.format("%04x", o.getManufacturerid()));
            deviceTextfield.setText(String.format("%04x", o.getDeviceid()));
            revisionTextfield.setText(String.format("%04x", o.getRevision()));
            
            
        } else {
            manufacturerTextfield.setText("");
            deviceTextfield.setText("");
            revisionTextfield.setText("");
        }
    }```

Any ideas?

Etwas Offtopic: Wenn man eine neue Antwort schreibt, die aber dann als Edit in der vorherigen landet, bekommen dann die anderen Thread-Teilnehmer eine Benachrichtigung dass es neue Antworten gibt?

Aber zurück zum Thema:

Hab weiter gelesen, das hier sollte her passen um ein Objekt im Lookup zu registrieren:

InstanceContent ic = new InstanceContent();
Lookup lookup = new AbstractLookup(ic);
ic.add(device);

… geht aber auch nicht?!

Könnte aber auch am Listener liegen dass da noch etwas nicht stimmt. Hmmpf. Bin weiterhin offen für Anregungen und Tipps.

*** Edit ***

Ich steig immer noch nicht ganz durch… Ich schätze ich hab das Prinzip noch nicht ganz verstanden.

  • Ist dieses Lookup jetzt global (eine „Map“ für die ganze Anwendung), oder hat jede „TopComponent“ ihren eigenen Lookup? Hier steht:

There is already a global lookup, which any modules can Listen to.
It is called Utilities.actionsGlobalContext();
It actually proxies to the Lookup of the currently active TopComponent.

Das lässt mich annehmen dass jede TopComponent ihre eigene LookupMap führt, und ich über actionGlobalContext() den Lookup der gerade selektierten/aktiven TopComponent erhalte?! Ist das soweit korrekt?

Wenn ja, dann hab ich das Prinzip völlig falsch angenommen. Dachte bisher dass lookup eine Art „globale Registry“ ist in der man an beliebiger Stelle Objekte reinstecken, und an beliebig anderer Stelle änderungen/neue Objekte per Listener mitkriegt.

Wenn jetzt jede Komponente ihr eigenes Lookup hat, dann wird das doch schnell unübersichtlich und konfus?! Ich kann mir zwar augenscheinlich mit

TopComponent tc = WindowManager.getDefault().findTopComponent("DeviceEditorTopComponent");
Lookup tcLookup = tc.getLookup();

den Lookup der „Ziel-Komponente“ holen, aber wie stecke ich da mein „Device-Objekt“ rein für das sich die Ziel-Komponente interessiert?

Auch verstehe ich dann nicht wie ich folgendes konkret umsetzen soll:

Ich hätte gerne einen Toolbar-Button mit dem ich einen FileChooser-Dialog bekomme (den Dialog hab ich selbst gebaut und kein Netbeans-Modul/API benutzt → Fehler?), eine File auswähle, nach der Auswahl die File lese (bis hierher hab ich’s) und das Ergebnis dann an eine TopComponent weiterreiche…

Wäre echt toll wenn sich ein Netbeans-Auskenner hier outet und mir vllt. ein kleines Bespiel geben kann.

Gruß
Alex