JavaFX Beans Binding funktioniert plötzlich nicht mehr

Lesezeit: 4 Minuten

Ich verwende JavaFX NumberBindings, um bestimmte Werte zu berechnen. Zunächst funktioniert alles wie erwartet. Nach relativ kurzer Zeit funktioniert die Bindung jedoch einfach nicht mehr. Ich bekomme auch keine Exception.

Ich habe mehrere Bindungen sowie Ansätze auf hoher und niedriger Ebene ausprobiert. Sogar die Berechnung selbst (wenn überschrieben) stoppt einfach und wird nicht mehr aufgerufen. Ich habe auch auf das neueste JDK (1.8.0_05) aktualisiert und alles neu erstellt/neu gestartet.

Das folgende minimale Arbeitsbeispiel veranschaulicht das Problem. Es sollte System.out.println die aktuelle Breite des Hauptfensters auf STDOUT. Nachdem die Größe des Fensters für etwa 10 Sekunden geändert wurde, stoppt die Ausgabe einfach. Ich habe auch versucht, die resultierende Eigenschaft an ein JavaFX-Steuerelement zu binden, um die weitere Verwendung der Eigenschaft sicherzustellen, aber das war erfolglos. Ich glaube, ich vermisse hier ein sehr grundlegendes Verhalten der Eigenschaften/Bindungen, Google scheint dieses Verhalten überhaupt nicht zu kennen.

import javafx.application.Application;
import javafx.beans.binding.NumberBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class BindingsProblem extends Application {

@Override
public void start(Stage primaryStage) {
    // Initialization...
    StackPane root = new StackPane();
    Scene scene = new Scene(root, 300, 250);
    primaryStage.setScene(scene);
    primaryStage.show();


    // Binding - The problem occurrs here!
    NumberBinding currentWidthPlusTen = primaryStage.widthProperty().add(10);
    IntegerProperty boundNumberProperty = new SimpleIntegerProperty();
    boundNumberProperty.bind(currentWidthPlusTen);
    boundNumberProperty.addListener(new ChangeListener<Number>() {

        @Override
        public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
            System.out.println(newValue.toString());
        }

    });
}


public static void main(String[] args) {
    launch(args);
}

}

  • Ich kann das Problem reproduzieren. Es sieht aus wie ein Fehler. Haben Sie auf Jira gesucht?

    – Assylias

    21. Mai 2014 um 14:21 Uhr


  • Ich kann anscheinend keine vorhandenen Fehlerberichte finden. Es scheint etwas so Grundlegendes zu sein, dass es schwer vorstellbar ist, dass es sich um einen Fehler im JDK/JRE selbst handelt.

    – unterkuerbis

    21. Mai 2014 um 15:09 Uhr

JavaFX Beans Binding funktioniert plotzlich nicht mehr
James_D

Die Bindung verwendet a Schwacher Zuhörer um den Wert von zu beobachten currentWidthPlusTen. Da Sie keinen Verweis auf die halten boundNumberPropertyes ist für die Garbage Collection geeignet, sobald die start(...) Methode beendet. Wenn der Garbage Collector einsetzt, geht die Referenz vollständig verloren und die Bindung funktioniert nicht mehr.

Um dies direkt zu sehen, fügen Sie die Zeile hinzu

root.setOnMousePressed( event -> System.gc());

zum start(...) Methode. Sie können den Listener zwingen, “aufzuhören zu arbeiten”, indem Sie auf das Fenster klicken.

Offensichtlich ist das nicht das, was Sie wollen: Die Lösung besteht darin, den Verweis auf beizubehalten boundNumberProperty nach dem start(...) Ausgänge. Zum Beispiel:

import javafx.application.Application;
import javafx.beans.binding.NumberBinding;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class BindingsProblem extends Application {

    IntegerProperty boundNumberProperty;

    @Override
    public void start(Stage primaryStage) {
        // Initialization...
        StackPane root = new StackPane();
        Scene scene = new Scene(root, 300, 250);
        primaryStage.setScene(scene);
        primaryStage.show();

        // Binding - The problem occurrs here!
        NumberBinding currentWidthPlusTen = primaryStage.widthProperty()
                .add(10);

        boundNumberProperty = new SimpleIntegerProperty();
        boundNumberProperty.bind(currentWidthPlusTen);
        boundNumberProperty.addListener(new ChangeListener<Number>() {

            @Override
            public void changed(ObservableValue<? extends Number> observable,
                    Number oldValue, Number newValue) {
                System.out.println(newValue.toString());
            }

        });

    }

    public static void main(String[] args) {
        launch(args);
    }

}

Aktualisieren

Jeder, der auf dieses Problem stößt, sollte sich vielleicht auch Tomas Mikula’s ansehen ReactFX, die dafür eine sauberere Problemumgehung bietet (auf Kosten der Verwendung einer Bibliothek eines Drittanbieters, für die Sie einige Zeit zum Lernen aufwenden müssten). Tomas erklärt dieses Problem und wie ReactFX es löst dieses Blog und das nachfolgender Beitrag.

  • Sehr gut! Dies löste mein Problem. Ich vertraue und verlasse mich eher auf die automatische Speicher-/Referenzverwaltung in Java. Offensichtlich zu viel 😀

    – unterkuerbis

    21. Mai 2014 um 17:35 Uhr

  • Interessanterweise verwenden Sie dies meistens für etwas Reales, außerhalb der einfachen Arten von Tests in Ihrem Beispielcode, und das Problem verschwindet. Wenn Sie beispielsweise ein Etikett erstellen und dessen Text an Ihr binden IntegerProperty, dann behält das Label natürlich effektiv einen Verweis auf die Eigenschaft, sodass es nicht zur Müllabfuhr kommt. Nur gelegentlich tritt dieses Problem in einem realen Szenario auf, aber es ist sehr selten.

    – James_D

    21. Mai 2014 um 20:10 Uhr

  • Dieses Problem macht mich wahnsinnig, da eine Tonne meines Codes, der in 2.x funktioniert hat, jetzt “auf mysteriöse Weise” nicht mehr funktioniert. Ich wünschte, man könnte zumindest kontrollieren, wann WeakListeners werden verwendet…

    – metasim

    9. Januar 2015 um 15:41 Uhr

831190cookie-checkJavaFX Beans Binding funktioniert plötzlich nicht mehr

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy