1

OpenJFX 11.0.1 で SimpleStringProperty を拡張して、機能を追加しようとしています。しかし、そう簡単ではないように思えます。拡張されたプロパティの奇妙な動作を経験しましたが、その理由はわかりません。うまくいくはずだと思います。

このサンプル コードの簡略化された SimpleStringProperty 拡張機能には、バインドされた TextField にユーザーが入力するたびに更新する必要がある別の読み取り専用文字列プロパティが含まれています。この場合、許可されていない文字をすべて削除し、プレフィックスを変換します。(これは完璧ではありませんが、表示するには十分短いことは承知しています)

サンプル コードを開始すると、コントロールの行を含むウィンドウが表示されます。「001 (242) 555666」のような文字列を入力すると、ラベルには「+1242555666」のような正規化された電話番号が表示されます。

  • 最初の変換は正しく機能します。
  • 例外はありません。
  • 新しい数字を入力すると、変換が呼び出されます。

しかし、数秒後に入力して削除すると、TextField への双方向バインディングによってプロパティの set() メソッドがトリガーされなくなります。

例を単純化するために、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