6

Java FX プロパティは、開発者が標準の get/set メソッド セマンティクスを使用する代わりにプロパティを作成できるようにする優れた API です。また、変更へのサブスクリプション、基本的な型とコレクションのプロパティ式のサポートも追加します。C# には言語の一部としてプロパティがありますが、これらのプロパティは JavaFX コンテナー内でのみ使用できます。つまり、変更をリッスンしようとIllegalStateExceptionすると、メインの JavaFX スレッド内でリスナー コードを実行する必要があるということわざに出くわします。

それでは、残りの Java の世界で利用できる代替手段はありますか?

アップデート

の例を次に示しIllegalStateExceptionます。JavaFX API を誤用していませんか?

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("s1");
        list.add("s2");

        ObservableList<String> observableList = FXCollections.observableList(list);
        observableList.addListener(new ListChangeListener<String>() {
            @Override
            public void onChanged(Change<? extends String> change) {
                System.out.println("added: " + change.getAddedSubList());
            }
        });

        observableList.add("s3");
    }
}

例外:

Exception in thread "main" java.lang.IllegalStateException
    at com.sun.javafx.collections.NonIterableChange.checkState(NonIterableChange.java:101)
    at com.sun.javafx.collections.NonIterableChange.getPermutation(NonIterableChange.java:81)
    at javafx.collections.ListChangeListener$Change.wasPermutated(ListChangeListener.java:156)
    at javafx.collections.ListChangeListener$Change.getAddedSubList(ListChangeListener.java:212)
    at Test$1.onChanged(Test.java:23)
    at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:134)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
    at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
    at com.sun.javafx.collections.ObservableListWrapper.add(ObservableListWrapper.java:154)
    at com.sun.javafx.collections.ObservableListWrapper.add(ObservableListWrapper.java:144)
    at Test.main(Test.java:27)
4

1 に答える 1

6

答え

JavaFX プロパティは、JavaFX システムの残りの部分とは独立して使用できます。また、アクティブな JavaFX シーン グラフに影響を与えないオブジェクトのプロパティのリスナー コードを JavaFX アプリケーション スレッドで実行する必要はありません。

説明

JavaFX アプリケーション スレッドでリスナー コードを実行する必要があるのは、変更されたリスナーまたはバインディングがシーン グラフ内のノードのプロパティに影響する場合のみです。

アプリケーションは、ノードをシーンにアタッチし、すでにシーンにアタッチされているノードを JavaFX アプリケーション スレッドで変更する必要があります。

JavaFX プロパティを使用し、ノードやシーン グラフを持たない Java プログラムを作成できます。シーン グラフと対話しないオブジェクトに対して、JavaFX 以外のスレッドで実行可能なプロパティを提供し、リスナーを変更できます。

サンプル

Oracle JavaFX プロパティとバインディングのチュートリアルでは、他の JavaFX コンポーネントを使用せず、JavaFX アプリケーション スレッドを持たないプログラムで JavaFX プロパティを使用する方法を示しています。

コメントの質問に基づく追加のサンプル

ありがとう、このチュートリアルの例は私にとってはうまくいきます。ただし、 ObservableList コレクションをリッスンしようとしたところ、この例外が発生しました。私は何か間違ったことをしていますか?

あなたは何か間違ったことをしています。

Java 8 で質問に追加したサンプル コードを実行してみましたが、エラー メッセージはより明確です。

スレッド「メイン」の例外 java.lang.IllegalStateException: 無効な変更状態: 変更を検査する前に next() を呼び出す必要があります。

呼び出しを追加するchange.next()と、テスト アプリケーションは期待どおりに機能します。

change.next()読み取りのためのjavadoc :

次の変更に進みます。初期状態では無効で、他のメソッドを呼び出す前に next() を呼び出す必要があります。最初の next() 呼び出しにより、このオブジェクトが最初の変更を表すようになります。

作業サンプルコード:

import javafx.collections.*;
import java.util.*;

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("s1");
        list.add("s2");

        ObservableList<String> observableList = FXCollections.observableList(list);
        observableList.addListener(new ListChangeListener<String>() {
            @Override
            public void onChanged(Change<? extends String> change) {
                while (change.next()) {
                    System.out.println("added: " + change.getAddedSubList());
                }
            }
        });

        observableList.add("s3");
    }
}

サンプルコードの出力:

added: [s3]
于 2013-10-23T20:07:35.427 に答える