Skip to main content
Entwickler Themen
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

8.2.4. Views und Bindings bearbeiten

Source, Design und Split zeigen dasselbe maßgebliche FXML-Dokument. Unterstützte Bearbeitungen ersetzen gezielt Quelltextbereiche, statt die komplette XML-Struktur neu zu serialisieren. Kommentare, Processing Instructions, fremde Attribute und unbeteiligte Formatierung bleiben erhalten. Eine akzeptierte Änderung bildet einen normalen Undo/Redo-Schritt des jeweiligen Hosts.

Layout und Component-Eigenschaften

Ein Objekt kann in der Hierarchie oder auf der Zeichenfläche ausgewählt werden. Unterstützt sind skalare Eigenschaften, Layoutwerte, Verschieben und Größenänderungen. Das betrifft auch geschachtelte oder anonyme Components und geeignete fx:root-Inhalte. Ein Ziehen an einer Ecke ändert Breite und Höhe gemeinsam in einer Transaktion.

Nicht jede beliebige FXML-Struktur lässt sich über einen visuellen Inspektor ausdrücken. Nicht unterstützte Strukturvorschläge werden abgelehnt. Für die unten beschriebenen Operationen gibt es das gemeinsame Strukturwerkzeug; andere Änderungen erfolgen in Source.

Eine Besonderheit betrifft importierte Anwendungstypen, die gar keine Components sind. Beispielsweise kann <Role fx:constant="..."/> in der Host-Projektion als Component fehlinterpretiert werden. Das Referenzbeispiel füllt die ChoiceBox deshalb im Controller mit Role.values(). Dies ist eine Einschränkung des Designers und keine allgemeine Regel für NeitzelLib oder FXMLLoader.

Properties und Ziele entdecken

Nach einem erfolgreichen Build und der Model-Deklaration der View zeigt Bindings die Model-Attribute, geschachtelte Pfade, das ausgewählte ViewModel und passende Ziel-Properties. Bei Sammlungen werden außerdem Elementtypen sowie kompatible Components und Rows berücksichtigt.

Ein gleicher Name beweist noch keine Kompatibilität. Entscheidend ist, welche Werte in der gewählten Richtung gelesen und geschrieben werden. Die zugrunde liegenden Laufzeitregeln erklärt das Kapitel Bindings in NeitzelLib.

Bereich Bearbeitung Beispiel
Direct bindings Ziel, Property, Model-Pfad, Richtung und optionalen Converter wählen; anlegen, ändern oder entfernen nameField.text und name, Alter über AgeConverter
Computed bindings Ziel und öffentliche parameterlose Controller-Methode wählen greetingLabel.text aus DeskController.greeting()
Repeat Pane, direktes Collection-Attribut und kompatible Component wählen visits als mehrere VisitForm-Instanzen
Table / Columns Sammlung, Row und geordnete Columns konfigurieren visitTable mit VisitRow
Structure Identifier umbenennen, Teilbaum kopieren/einfügen oder löschen Eine Layoutgruppe mit neuen eindeutigen IDs duplizieren
Problems Probleme öffnen und eine angebotene Korrektur ausdrücklich auswählen Ungültige DirectBinding-Richtung korrigieren
Generate View Ein neues Formular vor der Erzeugung prüfen Weitere Person-View aus gemeinsamen Metadaten

DirectBinding und Converter

Der Inspektor legt DirectBinding-Deklarationen an und bearbeitet vorhandene. Das Formular benennt control, property, path, direction und gegebenenfalls den Converter. Die Änderung wird erst mit Apply übernommen.

Alle drei Richtungen initialisieren das Steuerelement aus dem Model. Danach überträgt view Änderungen vom Model zur View, model von der View zum Model und both in beide Richtungen. ObservableList-Attribute verwenden eine gemeinsam genutzte Liste; ihre Änderungen folgen nicht diesen skalaren Richtungs- und Converter-Regeln.

Converter werden anhand kompilierter Klassen erkannt, ohne sie zu konstruieren. Ausdrückliche Fähigkeitsangaben ermöglichen passende Vorschläge. Ein unannotierter Converter kann zur Laufzeit korrekt sein und trotzdem als ungeprüft gekennzeichnet werden. Ein solcher Hinweis ist von einem bekannten Typfehler zu unterscheiden. Die tatsächliche Umwandlung bleibt Anwendungscode und benötigt passende Tests.

Die optionale Annotation heißt de.neitzel.fxdesigner.preview.ConverterCapabilities und liegt im Artefakt de.neitzel.fxdesigner:designer-preview-api:0.1.0-SNAPSHOT. Ein konkreter Integer-/String-Converter kann seinen Vertrag beispielsweise so angeben:

import de.neitzel.fxdesigner.preview.ConverterCapabilities;
import de.neitzel.fx.view.Converter;
import jakarta.inject.Singleton;

@Singleton
@ConverterCapabilities(modelType = Integer.class,
        controlType = String.class, reverse = true)
public class IntegerTextConverter implements Converter {
    public Object toControlValue(Object value) {
        return value == null ? "" : value.toString();
    }
    public Object toAttributeValue(Object value) {
        String text = (String) value;
        return text.isBlank() ? null : Integer.valueOf(text);
    }
}

Die Annotation wird auf der konkreten Klasse deklariert und nicht an Unterklassen vererbt. modelType und controlType beschreiben die Ein- und Ausgabetypen. Die Vorwärtsrichtung ist immer erforderlich, auch für die Initialisierung eines model-Bindings. model und both benötigen zusätzlich reverse=true und eine tatsächlich implementierte toAttributeValue-Methode. Boxing und Typzuweisung werden in jeder benötigten Richtung geprüft. Für komplexe und Collection-Attribute umgeht NeitzelLib Converter; dafür werden keine passenden Converter vorgeschlagen.

Diese Metadaten sind freiwillig. Das vorhandene AgeConverter-Beispiel darf ohne Annotation und mit entsprechendem Hinweis weiterverwendet werden. Wer eine Klasse unter src/main/java annotiert, muss die API bereits beim Kompilieren dieser Klasse und für die Designer-Erkennung verfügbar machen; eine ausschließlich testbezogene Dependency genügt dafür nicht. Benannte Module benötigen beim Einsatz der Annotation requires de.neitzel.fxdesigner.preview;. Diese Abhängigkeit wird somit nicht pauschal jeder NeitzelLib-Anwendung hinzugefügt. Die Annotation verändert weder das Converter-Interface noch dessen Laufzeitverhalten und beweist nicht die Korrektheit der Implementierung. Den vollständigen Vertrag beschreibt die Converter-Validierung im Repository.

ComputedBinding

ComputedBinding verwendet ausschließlich Ziel-Control, Ziel-Property und Controller-Methode. Die Methode muss öffentlich sein, darf keine Parameter haben und muss einen passenden Wert zurückgeben. Die Vorschläge verwenden #method; bestehende unpräfigierte Namen werden weiterhin akzeptiert. Es gibt hier keine Felder für Model-Pfad, Richtung, beobachtete Pfade oder Converter.

Bei einer Component ist diese selbst der Controller ihrer fx:root-View. Die Erkennung führt Methoden nicht aus. Eine kompatible Signatur beweist weder, dass die Methode erfolgreich läuft, noch dass ihr Aktualisierungsverhalten für die Anwendung ausreicht.

Belegt bereits ein Direct- oder Computed-Binding dasselbe Ziel, erfordert der Wechsel Replace conflicting bindings. Das Entfernen des bisherigen und Anlegen des neuen Bindings erfolgt dann gemeinsam. Unbekannte verschachtelte Deklarationsformen werden nicht in eine vermeintlich einfachere Schreibweise umgewandelt; dafür bleibt Source verfügbar.

Repeat, Table und Columns

Repeat wählt eine geeignete Pane und eine Component, deren Model zum Elementtyp der Sammlung passt. Repeat und Table verwenden ein direktes Collection-Attribut beziehungsweise eine Property des aktuellen ViewModels. Die geschachtelte Punktnotation von DirectBinding wird hier nicht automatisch übernommen.

Bei Table kommen geordnete Columns und der Row-Typ hinzu. Der Designer vergleicht die Columns mit den deklarierten Zellen der Row. Fehlende oder mehrdeutige Typinformationen werden gemeldet, statt passende Typen zu raten. Open Row Component öffnet die zugehörige FXML-Definition separat. Das Bearbeiten einer wiederholten Darstellung oder Tabellenzeile erzeugt keine neue Java-Component-Klasse.

Referenzen bei Strukturänderungen

Das Umbenennen von fx:id aktualisiert unterstützte Binding-Ziele sowie gewöhnliche $id-, einfache ${id.property}-, fx:reference- und fx:copy-Referenzen. Kopieren vergibt beim Einfügen neue IDs für die betroffenen Nachfahren und übernimmt die zugehörigen Bindings. Löschen entfernt den Teilbaum und Bindings, die auf dessen Objekte zielen.

Java-Controllerfelder, Model-Pfade und separate Component-Dateien werden dadurch nicht refaktoriert. Komplexe Ausdrücke, Skripte oder unbekannte Referenzkonventionen benötigen eine Prüfung in Source.

Einfügen unterstützt die Kinder üblicher VBox-, HBox-, Pane-, AnchorPane-, StackPane-, FlowPane-, TilePane- und GridPane-Container. Die Zwischenablage gehört zum jeweiligen Host-Prozess und kann zwischen dessen Editoren verwendet werden. Sie ist weder die Betriebssystem-Zwischenablage noch ein Transfer zwischen IntelliJ und Standalone.

Beim Einfügen in eine andere View bleiben deren Model und Controller erhalten; die übernommenen Bindings werden im Zielkontext geprüft. Mehrdeutige Imports, relative Ressourcen über View-Grenzen, Includes, Skripte, das Kopieren oder Löschen der Dokumentwurzel und nicht unterstützte Child-Properties benötigen Source-Bearbeitung. Native Kit-Aktionen zum Umhängen oder Löschen umgehen diese Regeln nicht.

Probleme, Navigation und Korrekturen

Bindings → Problems zeigt aktuelle Diagnosen. Die Auswahl navigiert zur betroffenen FXML-Stelle; die Source-Ansicht unterstreicht die entsprechenden Bereiche. IntelliJ ergänzt native Problems-Einträge, XML-Annotationen und Alt+Enter-Aktionen.

Fehler verhindern neue Vorschauen, nicht das Speichern eines unfertigen Entwurfs. Warnungen bleiben sichtbar und erlauben die Vorschau. Nach Änderungen werden veraltete Diagnosen und Korrekturen zurückgezogen. Es handelt sich um die Prüfung geöffneter Designer-Dokumente, nicht um einen vollständigen Hintergrundscan aller Projektdateien oder eine präzise Navigation zu Java-Ursprüngen.

Die angebotenen Korrekturen sind bewusst begrenzt: gültige DirectBinding-Richtungen, Entfernen einer späteren doppelten Direct-/Computed-Zielbelegung sowie Entfernen bestimmter einfacher ungültiger Direct-, Computed- und Repeat-Deklarationen. Tabellen, unbekannte oder geschachtelte Nutzlasten, Warnungen und Deklarationen mit eigenem fx:id erhalten keine spekulative Löschaktion.

Eine Korrektur wird ausdrücklich ausgewählt und als ein Undo/Redo-Schritt übernommen. Sie gilt nur für die zugrunde liegende aktuelle Revision. Der Designer wendet keine alten Quelltextpositionen auf einen inzwischen geänderten Text an.