Как запретить Javafx Tableview перезагружать все отображаемые строки, когда изменяются только определенные элементы? - PullRequest
1 голос
/ 20 октября 2019

Я пытаюсь улучшить производительность Application с несколькими Tableviews, которые постоянно обновляются. При каждом обновлении изменяется только 1 элемент внутри ObservableList. Перезагрузка строк этих Tableviews и применение к этим строкам CSS-стилей значительно замедляют работу приложения.

Я посмотрел на то, что Tableviews перезагружает свои строки, и понял,что все строки постоянно восстанавливаются с нуля, независимо от типа изменения базового ObservableList. Изменение 1 элемента в области просмотра / 1 элемента вне области просмотра / полная замена списка приводит к точному количеству конструкций строк.

Есть ли способ предотвратить перезагрузку Javafx Tableviews всех отображаемых Rows, когда изменяется только определенное значение Items?

Другие возможные настройки для повышения производительности при постоянной перезагрузке Tableviews будет принята с благодарностью.

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class FXApplication extends Application {

    private BorderPane border;
    private TableView<Item> tableView;
    private Button addItemToTv = new Button("Add");
    private Button replaceFirst = new Button("Replace first");
    private Button replaceLast = new Button("Replace last");
    private Button fullReplace = new Button("Full replace");

    private int counter = 0;

    protected Map<Integer, TableRow<Item>> rowsByIndex = new HashMap<>();

    @Override
    public void start(Stage primaryStage) {

        constructTv();
        setButtonActions();
        Scene s = constructScene();

        primaryStage.setScene(s);
        primaryStage.show();
    }

    private Scene constructScene() {
        border = new BorderPane();
        border.setCenter(tableView);
        border.setTop(new HBox(addItemToTv, replaceFirst, replaceLast, fullReplace));

        ScrollPane scp = new ScrollPane();
        scp.setFitToHeight(true);
        scp.setFitToWidth(true);
        scp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
        scp.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED);
        scp.setContent(border);

        return new Scene(scp);
    }

    private void setButtonActions() {
        addItemToTv.setOnAction(e -> {
            tableView.getItems().add(new Item("bla"));
            Platform.runLater(this::resetCounter);
        });
        replaceFirst.setOnAction(e -> {
            tableView.getItems().set(0, new Item("blub"));
            Platform.runLater(this::resetCounter);
        });
        fullReplace.setOnAction(e -> {
            ArrayList<Item> items = new ArrayList<>(tableView.getItems());
            tableView.getItems().setAll(items);
            Platform.runLater(this::resetCounter);
        });
        replaceLast.setOnAction(e -> {
            tableView.getItems().set(tableView.getItems().size()-1, new Item("blub"));
            Platform.runLater(this::resetCounter);
        });
    }


    private void resetCounter() {
        Timeline tl = new Timeline(new KeyFrame(Duration.millis(500), (ee) -> {
            System.out.println(counter + " row calls");
            counter = 0;
        }));
        tl.play();

    }

    private Node constructTv() {
        tableView = new TableView<>();
        for(int i = 0; i<10; i++){
            TableColumn<Item, String> col = new TableColumn<>("col " + i);
            col.setCellValueFactory(param -> {
                return new SimpleStringProperty(param.getValue().getString());
            });
            tableView.getColumns().add(col);
        }

        for (int i = 0; i < 30 ; i++) {
            tableView.getItems().add(new Item("bla"));
        }

        tableView.setRowFactory(param -> {
            TableRow<Item> row = new TableRow<>();
            row.itemProperty().addListener((observable, oldValue, newValue) -> {
                Platform.runLater(() -> {
                    rowsByIndex.put(row.getIndex(), row);
                    System.err.println("row change " + row.getIndex());
                    counter++;
                });
            });
            return row;
        });

        return tableView;
    }


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

}
class Item {
    private String string;

    public Item(String s) {
        string = s;
    }

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }
}
...