Java FX properties是一个很好的API,允许开发者创建属性,而不是使用标准的getset方法语义。它还增加了对变化的订阅,属性表达式对基本类型和集合的支持。虽然属性在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)
答
JavaFX属性可以独立于JavaFX系统的其他部分使用,并且没有要求不影响活动的JavaFX场景图的对象上的属性在JavaFX应用线程上运行其监听器代码。
解释
在JavaFX应用线程上运行监听器代码,只有当变更监听器或绑定影响到以下属性时才需要。节点 场景图中的节点。
一个应用程序必须在JavaFX应用程序线程上将节点附加到一个场景,并修改已经附加到场景的节点。
您可以编写使用JavaFX属性的Java程序,但没有节点或场景图。 您可以为没有与场景图交互的对象提供可在非JavaFX线程上执行的属性和更改监听器。
示例
神谕 JavaFX属性和绑定教程 演示在没有使用其他JavaFX组件和没有JavaFX应用线程的程序中使用JavaFX属性。
基于评论中的问题的附加示例
谢谢,这个教程中的例子对我来说很有用。但是我试着监听ObservableList集合,得到了这个异常。我是不是做错了什么?
你是做错了什么。
我试着在Java 8上运行你在问题中添加的示例代码,错误信息更加明确。
"main "线程出现异常 java.lang.IllegalStateException: Invalid Change state: next() Invalid Change state: next() must be called before inspecting the Change.
当你添加一个 change.next()
调用,你的测试应用程序的功能就会像你所期望的那样。
的javadoc。change.next()
改为。
转到下一个变化。在初始状态下是无效的一个需要在调用其他方法之前调用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]