1

我只是想在 OpenJFX 11.0.1 中扩展 SimpleStringProperty 以添加一些额外的功能。但是 ist 似乎并不那么容易,我经历了我的扩展属性的奇怪行为,我不知道为什么。我认为它应该工作。

我在此示例代码中简化的 SimpleStringProperty 扩展包含另一个只读字符串属性,每次用户键入绑定的 TextField 时都应更新该属性。在这种情况下,删除所有不允许的字符并转换前缀。(我知道这并不完美,但足够短,可以展示)

启动示例代码后,您将获得一个带有一行控件的窗口。键入“001 (242) 555666”之类的字符串,标签应显示标准化的电话号码,例如“+1242555666”。

  • 初始转换工作正常。
  • 我从来没有得到任何例外。
  • 当我输入新数字时调用转换。

但是,如果您在几秒钟后尝试键入和删除,则我的属性的 set() 方法不再由与 TextField 的双向绑定触发。

为了简化示例,我没有使用 TextFormatter。如果我使用一个,问题不会改变。

谁能帮我找出问题所在?

Windows 和 OS X 显示与 OpenJFX 11 和 OpenJFX 11.0.1 相同的行为

我用 JDK 1.8 尝试了相同的代码,它工作正常。

package testproperty;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;


public class TestProperty extends Application {

    // attempt to create an own property
    public class myPhoneNumberProperty extends SimpleStringProperty {

        private final ReadOnlyStringWrapper normalizedNumber = new ReadOnlyStringWrapper("");
        public ReadOnlyStringProperty normalizedNumberProperty() { return normalizedNumber.getReadOnlyProperty(); }
        public String getNormalizedNumber() { return normalizedNumber.get(); }

        public myPhoneNumberProperty() {
            super();
        }

        public myPhoneNumberProperty(String s) {
            super(s);
            calculate();
        }

        @Override
        public void set(String s) {
            super.set(s);
            calculate();
        }

        private void calculate() {
            // some calculations (only for test purposes)
            String original = this.get();
            String result = original.replaceAll("[^0123456789]","");
            if (result.startsWith("00")) result = result.replaceFirst("00", "+");
            if (original.startsWith("+")) result = "+".concat(result);
            normalizedNumber.set(result);
        }
    }


    @Override
    public void start(Stage primaryStage) {

        // create my property
        myPhoneNumberProperty phoneNumberA = new myPhoneNumberProperty("+34 952 111 222");

        // set up grid pane
        GridPane grid = new GridPane();
        grid.setPadding(new Insets(5,5,5,5));
        grid.setVgap(20);
        grid.setHgap(20);

        // set up the row
        Label labelA = new Label("Enter phone number");
        TextField textFieldA = new TextField();
        textFieldA.textProperty().bindBidirectional(phoneNumberA);
        Label labelB = new Label("Normalized number");
        Label labelN = new Label();
        labelN.textProperty().bind(phoneNumberA.normalizedNumberProperty());
        grid.addRow(0, labelA, textFieldA, labelB, labelN);

        // complete scene
        Scene scene = new Scene(grid, 1000, 100);
        primaryStage.setTitle("PhoneNumberProperty TestProg");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}
4

1 回答 1

1

您的phoneNumberA属性对象正在被垃圾收集。要解决此问题,您必须保持对该对象的强引用。一种选择是使其成为实例字段。

JavaFX 使用弱侦听器/引用实现绑定。双向绑定没有对其他属性的强引用。这与单向绑定不同,在单向绑定中,必须保留对可观察值的引用,以便以后解除绑定。

于 2019-01-04T08:05:01.530 回答