Java FX属性是一个很好的API,允许开发人员创建属性而不是使用标准的get / set方法语义。它还添加了对更改的订阅,属性表达式支持基本类型和集合。虽然C#中的属性作为语言的一部分,但这些属性仅在JavaFX容器内可用。即如果你try listening to changes,你会遇到一个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)
答案 0 :(得分:5)
<强>答案强>
JavaFX属性可以独立地用于JavaFX系统的其余部分,并且不要求对不影响活动JavaFX场景图的对象的属性在JavaFX应用程序线程上运行其侦听器代码。
<强>解释强>
仅当更改侦听器或绑定影响场景图中Nodes的属性时,才需要在JavaFX应用程序线程上运行侦听器代码:
应用程序必须将节点附加到场景,并在JavaFX应用程序线程上修改已附加到场景的节点。
您可以编写使用JavaFX属性且没有节点或场景图的Java程序。您可以提供属性并更改可在非JavaFX线程上执行的侦听器,以查找与场景图没有交互的对象。
<强>示例强>
Oracle JavaFX properties and binding tutorial演示了在不使用其他JavaFX组件且没有JavaFX应用程序线程的程序中使用JavaFX属性。
基于评论中的问题的其他示例
谢谢,本教程中的示例适用于我。但是我试着听ObservableList集合并得到了这个例外。我做错了吗?
你做错了什么。
我尝试在Java 8上运行您添加到问题中的示例代码,错误消息更明确:
线程“main”中的异常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]