- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 JavaFX 应用程序,它与服务器通信并从服务器获取数据。接收到的数据放入 ObservableList 中并显示在 TableView 中。
与服务器的通信在其自己的线程中运行,当调用 ObservableList.add 时,它会触发 IllegalStateException(提示不是事件线程/不是 JavaFX 线程)
我发现了以下solution类似的问题,但我不确定如何采用这种方法,因为在我的情况下,与服务器的通信需要不断地保持,因此任务/线程正在运行,直到通信终止。
我这里有一个最小的工作示例,它会触发所述异常并大致模拟应用程序的工作方式。
主要:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Controller :
package sample;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
public class Controller {
public TableView<Integer> timeTable;
public TableColumn<Integer, String> positionColumn;
private ObservableList<Integer> testList;
@FXML
private void initialize() {
testList = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
positionColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().toString()));
timeTable.setItems(testList);
Task<Integer> integerTask = new Test(testList);
Thread testThread = new Thread(integerTask);
testThread.start();
}
}
沟通任务:
package sample;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
public class Test extends Task<Integer> {
private ObservableList<Integer> testlist;
Test(ObservableList<Integer> list) {
testlist = list;
}
@Override
protected Integer call() throws Exception {
// Emulates the server communication thread. Instead of an endless loop, I used a fixed number of iterations.
// The real application has an endless while loop for server communication so a Task cannot be used to
// get the data
// getDataFromServer()
// parseData()
// putDataInList()
// loop
Thread.sleep(2000);
for (int i = 0; i < 500; ++i) {
testlist.add(i);
}
return 0;
}
}
FXML:
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:controller="sample.Controller"
xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
<TableView fx:id="timeTable" editable="true" prefHeight="498.0"
prefWidth="254.0">
<columns>
<TableColumn fx:id="positionColumn" prefWidth="73.0" text="Position"/>
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
</columnResizePolicy>
</TableView>
</GridPane>
最佳答案
即使列表是同步的,列表的修改仍然会触发执行修改的线程上的事件。在您的情况下,这会导致在非应用程序线程上触发 TableView
更新。
此外,您不能简单地使用 Task.updateValue
,请参阅 the javadoc 的以下部分(强调我的):
Calls to
updateValue
are coalesced and run later on the FX application thread [...] and intermediate values may be coalesced to save on event notifications.
您需要自己同步。以下类结合更新来补偿快速更新,快速更新可能会通过发布许多可运行对象来减慢应用程序线程的速度:
public abstract class JavaFXWorker<T> implements Runnable {
private final List<T> results = new LinkedList<>();
private final Object lock = new Object();
private boolean updateWaiting = false;
protected void publish(T... values) {
synchronized (lock) {
for (T v : values) {
results.add(v);
}
// don't trigger additional updates, if last update didn't fetch the results yet
// this reduces the number of Runables posted on the application thread
if (!updateWaiting) {
updateWaiting = true;
Platform.runLater(this::update);
}
}
}
private void update() {
List<T> chunks;
synchronized(lock) {
// copy results to new list and clear results
chunks = new ArrayList(results);
results.clear();
updateWaiting = false;
}
// run ui updates
process(chunks);
}
protected abstract void process(List<T> chunks);
}
您的代码可以使用上面的类重写如下。
public class Test extends JavaFXWorker<Integer> {
private final ObservableList<Integer> testlist;
public Test(ObservableList<Integer> list) {
testlist = list;
}
@Override
public void run() {
// Emulates the server communication thread. Instead of an endless loop, I used a fixed number of iterations.
// The real application has an endless while loop for server communication so a Task cannot be used to
// get the data
// getDataFromServer()
// parseData()
// putDataInList()
// loop
Thread.sleep(2000);
for (int i = 0; i < 500; ++i) {
publish(i);
}
}
@Override
protected process(List<Integer> chunks) {
testlist.addAll(chunks);
}
}
testList = FXCollections.observableArrayList();
...
Thread testThread = new Thread(new Test(testList));
testThread.start();
关于JavaFX 和多线程 : IllegalStateException on ObservableList. add(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47233533/
我有一个有趣的问题,我是 JavaFX 的新手,我需要创建一个小众市场 ObservableList执行。 本质上,我需要一个 ObservableList维护另一个 ObservableList 的
如果我有两个单独的 ObservableLists,并且都放在一个单独的 ObservableList 中用于 TableView...有没有办法在这两个 ObservableLists 和聚合的 O
当我尝试将项目设置到 tableView 中时遇到问题,有关我使用 SceneBuilder 的信息。 Main.java: public class Main extends Application
我想知道为什么TableView方法setItems不需要ObservableList作为参数,但是 ObservableList ? 还有什么是最好的转型方式ObservableList至Obser
当我将监听器附加到可观察列表并在该监听器中尝试删除一些元素时,在某些情况下它会通过,而在某些情况下会崩溃。 场景:项目已从列表中删除。它触发监听器,在该监听器中我尝试删除另一个项目。 如果在监听器中我
我在不同的条件下尝试了不同的集合,但我能够收到的所有更改都是排列、添加、删除和替换更改。 更新变化在什么条件下出现?什么基类,什么存储类以及需要什么操作来产生这样的事件? 最佳答案 要生成更新事件,您
This answer为可观察列表提供解决方案,如果列表元素的属性更改,它将发送“列表已更新” 通知>. 在我的例子中,此类可观察列表的元素(元素类)很复杂,我不喜欢为每个成员变量实现属性。因此,我在
这是我的问题:我有一堂 Detenu 课: public class Detenu { private static String n_ecrou; // Unique id p
我正在使用 JavaFX 编写日志读取器应用程序,并且我想根据所选属性实现基于搜索的过滤。 Application screenshot组合框中的值表示填充表的对象字段的名称。现在,我只想显示属性包含
给出以下代码示例: private final ObservableList data = FXCollections.observableArrayList( new Per
我有一个使用 JavaFX 的应用程序。它包含一个ListView(它使用ObservableList)。我使用添加了一个 ChangeListener list.getSelectionModel(
我有一个可观察列表,我尝试通过不同的谓词来过滤它。 我有要进行过滤的嵌套对象。 这是第一个 pojo public Class Transaction { private String na
例如,如果您有一个ArrayList,您可以执行以下操作: ArrayList list = new ArrayList(); ObservableList data = FXCollections.
我不太确定如何表达这个问题,请耐心等待。 我有一个 ObservableList用户定义的对象与几个 getter 方法,例如: public String getName() { return th
编辑 事实证明,当我实际上想要一个深拷贝时,FXCollections.observableArrayList() 正在创建列表的浅拷贝。 this.value 和 value “指向”两个不同的 O
我正在处理一个 javaFx 项目,我们必须在其中使用 ObservableList 添加 Listner。 ObservableList 包含人的模型。但是我想通过序列化将整个 Observable
我有一个自定义对象 FermentableInRecipe,它填充了一个 TableView。为了响应列表中项目的更改以及列表本身,我决定使用提取器。这是我的 ObservableList 的声明和实
我试图理解 ObservableList 和 Realms 的概念。我试图创建一个 ObservableList 的实例,如下所示: public ObservableList createObs
我有一个 Java ObservableList有数千个条目每秒接收数百个更新支持 JavaFX TableView . ObservableList 是 backed by an ArrayList
我有一张 Albums 的表格可由用户过滤和排序。 这是这张 table 的样子。如您所见,列是可排序的,顶部有一个文本框,当前正在过滤其中包含字符串“cu”的专辑: 一切正常专辑列表填充后 . 但是
我是一名优秀的程序员,十分优秀!