我正在尝试提高不断更新的Application
倍数的性能。Tableviews
在每次更新中,只有 1 项ObservableList
更改。重新加载这些行Tableviews
并将 css 样式应用于这些行正在显着降低应用程序的速度。
我查看了Tableviews
重新加载行的方式,并意识到所有行都在不断地从头开始重建,而与底层的更改类型无关ObservableList
。更改视口内的 1 个项目/视口外的 1 个项目/完全替换 List 会导致行构造的确切数量。
有没有办法阻止 JavafxTableviews
重新加载所有显示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;
}
}