当只有某些项目发生更改时,如何防止Javafx Tableview重新加载所有显示的行?
我试图通过不断更新的多个当只有某些项目发生更改时,如何防止Javafx Tableview重新加载所有显示的行?,java,performance,javafx,javafx-tableview,Java,Performance,Javafx,Javafx Tableview,我试图通过不断更新的多个表视图来提高应用程序的性能。每次更新时,可观察列表中只有1项发生更改。重新加载那些tableview的行,并将css样式应用于这些行,会显著降低应用程序的速度 我观察了tableview重新加载它们的行的方式,并意识到所有行都在不断地从零开始重构,而不依赖于对底层observeList的更改类型。更改视口内的1个项目/视口外的1个项目/完全替换列表会导致行构造的确切数量 当只有某些项发生更改时,是否有方法防止Javafx表视图重新加载所有显示的行 其他可能的调整,以提高性
表视图来提高应用程序的性能。每次更新时,可观察列表中只有1项发生更改。重新加载那些tableview
的行,并将css样式应用于这些行,会显著降低应用程序的速度
我观察了tableview
重新加载它们的行的方式,并意识到所有行都在不断地从零开始重构,而不依赖于对底层observeList
的更改类型。更改视口内的1个项目/视口外的1个项目/完全替换列表会导致行构造的确切数量
当只有某些项发生更改时,是否有方法防止Javafx表视图重新加载所有显示的行
其他可能的调整,以提高性能不断重新加载表视图
,将不胜感激
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;
}
}
导入javafx.animation.KeyFrame;
导入javafx.animation.Timeline;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.control.*;
导入javafx.scene.layout.*;
导入javafx.stage.stage;
导入javafx.util.Duration;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.Map;
公共类FXApplication扩展了应用程序{
私人边界;
私有TableView TableView;
专用按钮addItemToTv=新按钮(“添加”);
private Button replaceFirst=新按钮(“Replace first”);
private Button replaceLast=新按钮(“Replace last”);
专用按钮完全替换=新按钮(“完全替换”);
专用整数计数器=0;
受保护的映射rowsByIndex=newhashmap();
@凌驾
公共无效开始(阶段primaryStage){
constructv();
setButtoActions();
场景s=constructScene();
初级阶段.第二纪(s);
primaryStage.show();
}
私密场景{
border=新边框窗格();
border.setCenter(tableView);
setTop(新的HBox(additemtov、replaceFirst、replaceLast、fullReplace));
ScrollPane scp=新的ScrollPane();
scp.setFitToHeight(正确);
scp.setFitToWidth(真);
scp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_所需);
scp.setHbarPolicy(ScrollPane.ScrollBarPolicy.AS_所需);
scp.setContent(边框);
返回新场景(scp);
}
私有void setButtoActions(){
附加设置动作(e->{
tableView.getItems()添加(新项(“bla”);
Platform.runLater(this::resetCounter);
});
replaceFirst.setOnAction(e->{
tableView.getItems().set(0,新项(“blub”);
Platform.runLater(this::resetCounter);
});
fullReplace.setOnAction(e->{
ArrayList items=新的ArrayList(tableView.getItems());
tableView.getItems().setAll(项);
Platform.runLater(this::resetCounter);
});
替换last.setOnAction(e->{
tableView.getItems().set(tableView.getItems().size()-1,新项目(“blub”);
Platform.runLater(this::resetCounter);
});
}
私有无效重置计数器(){
时间线tl=新时间线(新关键帧(持续时间.毫秒(500),(ee)->{
System.out.println(计数器+“行调用”);
计数器=0;
}));
tl.play();
}
私有节点constructv(){
tableView=新的tableView();
对于(int i=0;i{
返回新的SimpleStringProperty(param.getValue().getString());
});
tableView.getColumns().add(col);
}
对于(int i=0;i<30;i++){
tableView.getItems()添加(新项(“bla”);
}
tableView.setRowFactory(参数->{
TableRow行=新TableRow();
row.itemProperty().addListener((可观察、旧值、新值)->{
Platform.runLater(()->{
rowsByIndex.put(row.getIndex(),row);
System.err.println(“行更改”+row.getIndex());
计数器++;
});
});
返回行;
});
返回表视图;
}
公共静态void main(字符串[]args){
FXApplication.launch(args);
}
}
类项目{
私有字符串;
公共项目(字符串s){
字符串=s;
}
公共字符串getString(){
返回字符串;
}
公共无效设置字符串(字符串){
this.string=string;
}
}
使用平台没有意义。请稍后运行时间线<代码>平台.runLater(this::resetCounter)代码>是无用的。此外,每次按下按钮,基本上都在创建新的时间线,并且所有时间线都在运行。这与高性能代码相反(可能不是,但使用了大量不必要的资源)。为什么在cell工厂中使用行侦听器?为什么要在cell工厂稍后运行platform.run。我觉得你做的每件事都与表演的理念背道而驰。您需要从一些基本的JavaFX教程开始。这只是一个虚拟程序,用于显示在对ObservableListener应用更改时调用RowListener的次数,我们知道这是一个示例—但正如@Sedrick已经指出的那样:看起来您所做的一切都是为了人为地减慢一切;)重复:无需在此处使用的任何位置调用Platform.runlater。您是否真的分析了您的应用程序,以及它揭示了哪些瓶颈?好的,我同意Platform.runlater i