简体   繁体   English

扩展 SimpleStringProperty 的问题

[英]Problem with extending SimpleStringProperty

I am just trying to extend a SimpleStringProperty in OpenJFX 11.0.1 to add some extra functionality.我只是想在 OpenJFX 11.0.1 中扩展 SimpleStringProperty 以添加一些额外的功能。 But ist seems not so easy, I experienced strange behavior of my extended Property and I don't know why.但似乎并不那么容易,我的扩展属性经历了奇怪的行为,我不知道为什么。 I think it should work.我认为它应该工作。

My in this sample code simplified SimpleStringProperty extension contains another readonly string property which should be updated every time the the user types into a bound TextField.我在此示例代码中简化的 SimpleStringProperty 扩展包含另一个只读字符串属性,每次用户键入绑定的 TextField 时都应更新该属性。 In this case remove all not allowed characters and convert the prefix.在这种情况下,删除所有不允许的字符并转换前缀。 (I know this is not perfect but short enough to show) (我知道这并不完美但足够短以显示)

After starting the sample code you will get a window with a rows of Controls.启动示例代码后,您将看到一个带有一行控件的窗口。 Typing in a String like "001 (242) 555666" the label should show the normalized phone number like "+1242555666".输入像“001 (242) 555666”这样的字符串,标签应该显示像“+1242555666”这样的规范化电话号码。

  • The initial conversion works correcty.初始转换工作正常。
  • I never get any exceptions.我从来没有得到任何例外。
  • The conversion is called when I type in new digits.当我输入新数字时调用转换。

But if you play around with typing and deleting after a few seconds the set() method of my property isn't longer triggered by the bidirectional binding to the TextField.但是,如果您在几秒钟后尝试键入和删除,则我的属性的 set() 方法不再由与 TextField 的双向绑定触发。

To simplify the example I didn't use a TextFormatter.为了简化示例,我没有使用 TextFormatter。 If I use one the problem doesn't change.如果我使用一个,问题不会改变。

Can anyone help me figure out the problem?谁能帮我找出问题所在?

Windows and OS X show the same behavior with OpenJFX 11 and OpenJFX 11.0.1 Windows 和 OS X 显示与 OpenJFX 11 和 OpenJFX 11.0.1 相同的行为

I tried the same code with JDK 1.8 and there it works fine.我在 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);
    }

}

Your phoneNumberA property object is being garbage collected.您的phoneNumberA属性对象正在被垃圾收集。 To fix this you must keep a strong reference to the object.要解决此问题,您必须保持对该对象的强引用。 One option is to make it an instance field.一种选择是使其成为实例字段。

JavaFX implements bindings using weak listeners/references. JavaFX 使用弱侦听器/引用实现绑定。 Bidirectional bindings have no strong references to the other property.双向绑定没有对其他属性的强引用。 This is different from unidirectional bindings where a reference to the observable value must be kept in order to unbind from it later.这与单向绑定不同,单向绑定必须保留对 observable 值的引用,以便稍后解除绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM