Entitätseditor erstellen

Editor-Klasse

Ein Editor, bzw. die Detailansicht ist meist eine Fenster, welches sich erst auf spezielle Benutzeraktion bei der Übersicht öffnet (z.B. Doppelklick mit der Maus, oder Druck auf ein Toolbar-Symbol, o.ä.). Dafür ist die Klasse AbstractDetailsView vorgesehen.

In besonderen Fällen kann es auch sinnvoll sein, die Detailansicht ständig anzuzeigen. Dafür ist dann die Klasse AbstractEditor vorgesehen, den Fall wollen wir jetzt hier nicht weiter vertiefen.

Fangen wir also mit unserer Detailansicht für Adressen an:

public class AddressesDetails extends AbstractDetailsView<Addresses> {
    private static final long serialVersionUID = 1L;

    public AddressesDetails(String id, Addresses instance) {
        super(id, instance);
    }

    @Override
    public JComponent createView() {
       ...
    }
} 

Das ist "alles" - für eine einfache Detailansicht. Die Klasse AbstractDetailsView enthält schon die ganze Logik, die zum Speichern etc. notwendig ist.

Formular erstellen

Die meiste Arbeit einer Detailansicht steckt in der Ausarbeitung des Formulars und somit in der Funktion createView. Hier ist JGoodies forms eine große Hilfe und es lohnt sich, sich eingehender mit der Dokumentation von JGoodies auseinander zu setzen. Es gibt auch einige sehr gute Tutorials zur Erstellung von Masken.

Ich habe festgestellt, dass es sehr hilfreich ist, kleine Skizzen auf Papier zu machen und sich so schon Gedanken über das Aussehen zu machen. Ich will jetzt hier keine komplette Maske runter beten, sondern nur aufs Prinzip eingehen.

FormLayout layout = new FormLayout("...");
PanelBuilder builder = new PanelBuilder(layout);

builder.setDefaultDialogBorder();
CellConstraints cc = new CellConstraints();

return builder.getPanel(); 

Der Kernpunkt ist das FormLayout, über das das spätere Fenster in ein Raster eingeteilt wird. Jeder Zelle kann eine feste oder eine variable Breite zugeteilt werden, die Zeilen können angegeben werden, oder von JGoodies erstellt werden. Ich ziehe ersteres vor, auch wenn es mehr Schreibarbeit darstellt. Dadurch ist eine genauere Kontrolle des Aussehens möglich - und das ist ja wichtig bei einer GUI-Anwendung. Wenn alle Elemente dem PanelBuilder zugefügt wurde, kann das erzeugte Formular mit builder.getPanel() angefordert werden.

Eine Erweiterung von SRJRCFrames besteht darin, die Texte auszulagern. Der Prompt für ein Eingabefeld wird z.B. so angelegt:

builder.addLabel(msgSource.getMessage("Addresses." + Addresses.FLD_CITY,
                                      null,
                                      "Addresses." + Addresses.FLD_CITY,
                                      null), cc.xy(1, 1)); 

msgSource ist ein Anwendungsdienst, der über den Dienste-Verwalter ApplicationServiceProvider angefordert werden kann. Der Dienste-Verwalter ist eine der wenigen Fabrikklassen mit statischen Methoden. Ansonsten wird von der Verwendung von öffentlichen statischen Methoden abgeraten - dafür gibt es ja schließlich den Kontext (siehe Konfiguration). Die Fabriken msgSource (für die Texte) und componentFactory (für die einheitliche Erstellung von Eingabeelementen) wurden bereits von der Superklasse angefordert. Die Anforderung sieht wie folgt aus:

if (msgSource == null)
   msgSource = ApplicationServiceProvider.getService(
                                 MessageSource.class);
if (componentFactory == null)
   componentFactory = ApplicationServiceProvider.getService(
                                 FormComponentFactory.class);

Von der Superklasse AbstractDetailsView wird die Instanz bereits in ein PresentationModel eingebettet, sodass die Attribute gepuffert editiert werden können (d.h. bei Abbrechen hat sich nix verändert). Ein Eingabefeld wird dann so angelegt:

JTextField tCity = componentFactory.createTextField(
                           getPresentationModel().
                           getBufferedModel(Addresses.FLD_CITY));

builder.add(tCity, cc.xyw(3, 1, 5));

Ein Eingabefeld kann sich auch über mehrere Zellen erstrecken. Dafür sind die CellConstraints. Hier sind eigene Experimente angesagt.