Java FX 属性是一个很好的 API,允许开发人员创建属性而不是使用标准的 get/set 方法语义。它还添加了对更改的订阅、对基本类型和集合的属性表达式支持。尽管属性作为语言的一部分存在于 C# 中,但这些属性仅在 JavaFX 容器内可用。 IE。如果你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):
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 系统的其余部分使用,并且不要求不影响 Activity JavaFX 场景图的对象的属性在 JavaFX 应用程序线程上运行其监听器代码。
解释
仅当更改监听器或绑定(bind)影响 Nodes 的属性时,才需要在 JavaFX 应用程序线程上运行监听器代码。在场景图中:
An application must attach nodes to a Scene, and modify nodes that are already attached to a Scene, on the JavaFX Application Thread.
您可以编写使用 JavaFX 属性且没有节点或场景图的 Java 程序。您可以为与场景图没有交互的对象提供属性并更改可在非 JavaFX 线程上执行的监听器。
示例
神谕 JavaFX properties and binding tutorial演示在不使用其他 JavaFX 组件且没有 JavaFX 应用程序线程的程序中使用 JavaFX 属性。
基于评论中问题的附加示例
Thanks, examples in this tutorial work for me. However I tried listening to the ObservableList collection and got this exception. Am I doing something wrong?
你做错了什么。
我尝试在 Java 8 上运行您添加到问题中的示例代码,错误消息更加明确:
Exception in thread "main" java.lang.IllegalStateException: Invalid Change state: next() must be called before inspecting the Change.
当你添加 change.next()
调用,您的测试应用程序将按预期运行。
change.next()
的 javadoc 如下:
Go to the next change. In initial state is invalid a require a call to next() before calling other methods. The first next() call will make this object represent the first change.
工作示例代码:
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]
关于java - 独立的 JavaFX 属性实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19549091/