Why can I update a TableView from a stream other than the UI but not a ListView?

In JavaFX, I discovered something strange (java version 1.8.0_91). As far as I understand, if you want to update the user interface from a separate stream, you need to either use Platform.runLater(taskThatUpdates)one of the tools in the package javafx.concurrent.

However, if I have TableViewwhich I am invoking .setItems(someObservableList), I can update someObservableListfrom a separate thread and see the corresponding changes in mine TableViewwithout the expected error Exception in thread "X" java.lang.IllegalStateException: Not on FX application thread; currentThread = X.

If replaced TableViewwith ListView, the expected error is expected.

Example code for the situation № 1: updating a TableViewanother thread, without having to call Platform.runLater()- and no errors.

public class Test extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        // Create a table of integers with one column to display
        TableView<Integer> data = new TableView<>();
        TableColumn<Integer, Integer> num = new TableColumn<>("Number");
        num.setCellValueFactory(v -> new ReadOnlyObjectWrapper(v.getValue()));
        data.getColumns().add(num);

        // Create a window & add the table
        VBox root = new VBox();
        Scene scene = new Scene(root);
        root.getChildren().addAll(data);
        stage.setScene(scene);
        stage.show();

        // Create a list of numbers & bind the table to it
        ObservableList<Integer> someNumbers = FXCollections.observableArrayList();
        data.setItems(someNumbers);

        // Add a new number every second from a different thread
        new Thread( () -> {
            for (;;) {
                try {
                    Thread.sleep(1000);
                    someNumbers.add((int) (Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

№ 2: a ListView , Platform.runLater() - .

public class Test extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        // Create a list of integers (instead of a table)
        ListView<Integer> data = new ListView<>();

        // Create a window & add the table
        VBox root = new VBox();
        Scene scene = new Scene(root);
        root.getChildren().addAll(data);
        stage.setScene(scene);
        stage.show();

        // Create a list of numbers & bind the table to it
        ObservableList<Integer> someNumbers = FXCollections.observableArrayList();
        data.setItems(someNumbers);

        // Add a new number every second from a different thread
        new Thread( () -> {
            for (;;) {
                try {
                    Thread.sleep(1000);
                    someNumbers.add((int) (Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

, data ListView<Integer>, a TableView<Integer>.

, ? - TableColumn::setCellValueFactory() ? - . , , , , , .setItems .

+4
1

@James_D, , FX, . ObservableList . , TableView ListView , .

Task, ObservableLists.

Task-API-Doc

,

ListView, TableView ObservableList, ObservableList . , ​​ ObservableList , .

:

,

, . , . , , TableView . FX, . , , FX.

- updateValue (Object). . FX. , , , .

Task ObservableLists TableView ListView:

import java.util.ArrayList;
import java.util.Random;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class IntermediateTest extends Application {

    @Override
    public void start(Stage primaryStage) {

        TableView<Integer> tv = new TableView<>();
        TableColumn<Integer, Integer> num = new TableColumn<>("Number");
        num.setCellValueFactory(v -> new ReadOnlyObjectWrapper(v.getValue()));
        tv.getColumns().add(num);
        PartialResultsTask prt = new PartialResultsTask();
        tv.setItems(prt.getPartialResults());

        ListView<Integer> lv = new ListView<>();
        PartialResultsTask prt1 = new PartialResultsTask();
        lv.setItems(prt1.getPartialResults());
        new Thread(prt).start();
        new Thread(prt1).start();

        // Create a window & add the table
        VBox root = new VBox();
        root.getChildren().addAll(tv, lv);
        Scene scene = new Scene(root, 300, 450);

        primaryStage.setTitle("Data-Adding");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    public class PartialResultsTask extends Task<ObservableList<Integer>> {

        private ReadOnlyObjectWrapper<ObservableList<Integer>> partialResults
                = new ReadOnlyObjectWrapper<>(this, "partialResults",
                        FXCollections.observableArrayList(new ArrayList()));

        public final ObservableList getPartialResults() {
            return partialResults.get();
        }

        public final ReadOnlyObjectProperty<ObservableList<Integer>> partialResultsProperty() {
            return partialResults.getReadOnlyProperty();
        }

        @Override
        protected ObservableList call() throws Exception {
            updateMessage("Creating Integers...");
            Random rnd = new Random();
            for (int i = 0; i < 10; i++) {
                Thread.sleep(1000);
                if (isCancelled()) {
                    break;
                }
                final Integer r = rnd.ints(100, 10000).findFirst().getAsInt();
                Platform.runLater(() -> {
                    getPartialResults().add(r);
                });
                updateProgress(i, 10);
            }
            return partialResults.get();
        }
    }

}
+4

All Articles