- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 javafx tableview 并创建了一个包含 100,000 行(三列 1 int 2 float)的表。
我开启了主动排序。要插入新行,我首先使用二进制搜索搜索索引,然后使用 table.getItems.add(index,element); 插入它;
但是随着每 20 毫秒添加新行,GUI 有点无响应。
我添加了 table.setSelectionModel(null); 并固定了我的 GUI,因此它似乎是 GUI 缓慢的罪魁祸首。
但我还需要选择行的能力.....
有人建议在这种情况下该怎么做......
P.S. :(在添加行 table.setSelectionModel(null); 之前,我尝试运行 jprofiler,它显示主要时间消耗在 javafx.scene .control.TableCell$2.onChanged )
编辑:
我的用例
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Random;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.SortType;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TableInsertExample extends Application {
int count=0;
long s,e,mx=0,mn=1000000000;
float avg=0;
private static final Random RNG = new Random();
private Comparator<Person> tableOrderComparator ;
@SuppressWarnings("unchecked")
@Override
public void start(Stage primaryStage) {
final BorderPane root = new BorderPane();
final TableView<Person> table = new TableView<Person>();
table.setItems(createData());
final TableColumn<Person, String> firstNameColumn = new TableColumn<Person,String>("First Name");
final TableColumn<Person, String> lastNameColumn = new TableColumn<Person,String>("Last Name");
firstNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
lastNameColumn.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
table.getColumns().addAll(firstNameColumn, lastNameColumn);
tableOrderComparator = createTableOrderComparator(table);
//this line increase speed but then we can not even click on table as it will give someexception
table.setSelectionModel(null);
final GridPane addPersonPane = new GridPane();
final TextField firstNameTF = new TextField();
final TextField lastNameTF = new TextField();
final Button addButton = new Button("Add");
addPersonPane.addRow(0, new Label("First Name:"), firstNameTF);
addPersonPane.addRow(1, new Label("Last Name:"), lastNameTF);
addPersonPane.addRow(2, addButton);
final ColumnConstraints leftColConstraints = new ColumnConstraints();
leftColConstraints.setHalignment(HPos.RIGHT);
final ColumnConstraints rightColConstraints = new ColumnConstraints();
rightColConstraints.setHalignment(HPos.LEFT);
addPersonPane.getColumnConstraints().addAll(leftColConstraints, rightColConstraints);
addButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
final Person person = new Person(firstNameTF.getText(), lastNameTF.getText());
addPersonToTable(table, person);
}
});
table.getSortOrder().addAll(firstNameColumn);
Label countLabel = new Label();
countLabel.textProperty().bind(Bindings.format("Table has %s entries", Bindings.size(table.getItems())));
root.setTop(countLabel);
root.setCenter(table);
root.setBottom(addPersonPane);
primaryStage.setScene(new Scene(root, 400, 600));
primaryStage.show();
Timeline addRandomPeopleFrequently = new Timeline(new KeyFrame(Duration.millis(20), new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Person randomPerson = new Person(randomString(), randomString());
count++;
addPersonToTable(table, randomPerson);
}
}));
addRandomPeopleFrequently.setCycleCount(Animation.INDEFINITE);
addRandomPeopleFrequently.play();
}
private Comparator<Person> createTableOrderComparator(
final TableView<Person> table) {
return new Comparator<Person>() {
@Override
public int compare(Person person1, Person person2) {
for (TableColumn<Person, ?> col : table.getSortOrder()) {
Comparator colComp = col.getComparator();
if (colComp == null) {
colComp = TableColumn.DEFAULT_COMPARATOR;
}
final Object o1 = col.getCellData(person1);
final Object o2 = col.getCellData(person2);
int c = colComp.compare(o1, o2);
if (col.getSortType() == SortType.DESCENDING) {
c = -c ;
}
if (c != 0) {
return c;
}
}
return 0 ;
}
};
}
public static void main(String[] args) {
launch(args);
}
private ObservableList<Person> createData() {
List<Person> list = new ArrayList<Person>();
for (int i=0; i<100000; i++) {
list.add(new Person(randomString(), randomString()));
}
return FXCollections.observableList(list);
}
private String randomString() {
StringBuilder sb = new StringBuilder();
for (int i=0; i<8; i++) {
sb.append((char)(RNG.nextInt(26)+'a'));
}
return sb.toString();
}
private void addPersonToTable(final TableView<Person> table,
final Person person) {
int index ;
final ObservableList<TableColumn<Person, ?>> tableSortOrder = table.getSortOrder();
if (tableSortOrder.size()==0) {
index = table.getItems().size();
} else {
index = Collections.binarySearch(table.getItems(), person, tableOrderComparator);
if (index < 0) {
index = -index-1 ;
}
}
s=System.currentTimeMillis();
List<Person> leftList = table.getItems().subList(0, index);
List<Person> rightList = table.getItems().subList(index, table.getItems().size());
List<Person> newList = new ArrayList<Person>(table.getItems().size()+1);
newList.addAll(leftList);
newList.add(person);
newList.addAll(rightList);
/* int selectedIndex = table.getSelectionModel().getSelectedIndex();
if (index < selectedIndex) {
selectedIndex++;
} */
table.getItems().setAll(newList);
// table.getSelectionModel().select(selectedIndex);
e= System.currentTimeMillis() - s;
avg+=e;
if(mx<e)
mx=e;
if(mn>e)
mn=e;
if(count==1000)
{
avg=avg/10000;
System.out.format("current System time is %f. Max is %d . Min is %d%n",avg,mx,mn);
count=0;
avg=0;
mx=0;
mn=100000000;
}
}
public static class Person {
private final StringProperty firstName ;
private final StringProperty lastName ;
Person(String firstName, String lastName) {
this.firstName = new SimpleStringProperty(this, "firstName", firstName);
this.lastName = new SimpleStringProperty(this, "lastName", lastName);
}
public String getFirstName() { return firstName.get(); }
public void setFirstName(String firstName) { this.firstName.set(firstName);}
public StringProperty firstNameProperty() { return firstName ; }
public String getLastName() { return lastName.get(); }
public void setLastName(String lastName) { this.lastName.set(lastName); }
public StringProperty lastNameProperty() { return lastName ; }
@Override public String toString() { return firstName.get() + " " + lastName.get() ; }
}
}
开头这一行
//this line increase speed but then we can not even click on table as it will give someexception
table.setSelectionModel(null);
帮助我增加平均插入速度到0.2 ms(计算平均值的代码包含在代码中)
但它禁用任何选择(由于这个原因,addPersonToTable 中的代码被注释)
我想要选择一行的能力,但这段代码具有一定的速度效率。 (我使用了 Jprofiler,它显示主要时间花在 TableCell.onChanged )
注意:此代码由 James_D 编写,我只是对其进行了一些修改(添加行 table.setSelectionModel(null); 和 addPersonToTable 中的注释行)
最佳答案
我无法重现您的问题。
将新行添加到具有 100,000 行的 TableView 中的排序位置对我来说几乎是即时的。
我使用了对 James 对您之前问题的回答的修改:JavaFx tableview sort is really slow how to improve sort speed as in java swing .
修改在按下添加按钮时执行以下算法:
如果您使用 Java 7,则 TableView 中存在错误 scrollTo阻止表格在所有情况下滚动到正确位置的例程。
使用 Java 8b93、Win7 的输出:
TableSortPerformanceTest.java
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.Random;
public class TableSortPerformanceTest extends Application {
public static final int INIT_LIST_SIZE = 100_000;
@Override
public void start(Stage stage) {
Scene scene = new Scene(new StackPane());
stage.setTitle("Table View Sample");
stage.setWidth(550);
stage.setHeight(550);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
final TableView<Person> table = new TableView<Person>();
table.setEditable(true);
TableColumn<Person, String> firstNameCol = new TableColumn<Person, String>("First Name");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("firstName"));
firstNameCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Person,String>, ObservableValue<String>>() {
@Override
public ObservableValue<String> call(CellDataFeatures<Person, String> cdf) {
return cdf.getValue().firstNameProperty();
}
});
TableColumn<Person, String> lastNameCol = new TableColumn<Person, String>("Last Name");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("lastName"));
TableColumn<Person, String> emailCol = new TableColumn<Person, String>("Email");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(
new PropertyValueFactory<Person, String>("email"));
final Random random = new Random();
for (int i = 0; i < INIT_LIST_SIZE; i++) {
table.getItems().add(new Person(randomString(random), randomString(random), randomString(random)));
}
table.getColumns().addAll(Arrays.asList(firstNameCol, lastNameCol, emailCol));
long start = new Date().getTime();
Collections.sort(table.getItems());
long end = new Date().getTime();
System.out.println("Took: " + (end - start));
final TextField addFirstName = new TextField();
addFirstName.setPromptText("First Name");
addFirstName.setMaxWidth(firstNameCol.getPrefWidth());
final TextField addLastName = new TextField();
addLastName.setMaxWidth(lastNameCol.getPrefWidth());
addLastName.setPromptText("Last Name");
final TextField addEmail = new TextField();
addEmail.setMaxWidth(emailCol.getPrefWidth());
addEmail.setPromptText("Email");
final Button addButton = new Button("Add");
addButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
String firstName = isEmpty(addFirstName.getText()) ? randomString(random) : addFirstName.getText();
String lastName = isEmpty(addLastName.getText()) ? randomString(random) : addLastName.getText();
String email = isEmpty(addEmail.getText()) ? randomString(random) : addEmail.getText();
Person person = new Person(firstName, lastName, email);
int idx = Collections.binarySearch(table.getItems(), person);
if (idx < 0) {
idx = -idx - 1;
}
table.getItems().add(idx, person);
table.getSelectionModel().select(idx);
table.scrollTo(idx);
addFirstName.clear();
addLastName.clear();
addEmail.clear();
}
});
final HBox hb = new HBox(3);
hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10));
vbox.getChildren().addAll(label, table, hb);
((StackPane) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private boolean isEmpty(String string) {
return (string == null || string.isEmpty());
}
private String randomString(Random random) {
char[] chars = new char[20];
for (int i = 0; i < 20; i++) {
int nextInt = random.nextInt(26);
nextInt += random.nextBoolean() ? 65 : 97;
chars[i] = (char) nextInt;
}
return new String(chars);
}
public static class Person implements Comparable<Person> {
private final StringProperty firstName;
private final StringProperty lastName;
private final StringProperty email;
private Person(String fName, String lName, String email) {
this.firstName = new SimpleStringProperty(fName);
this.lastName = new SimpleStringProperty(lName);
this.email = new SimpleStringProperty(email);
}
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public StringProperty firstNameProperty() {
return firstName ;
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
public StringProperty lastNameProperty() {
return lastName ;
}
public String getEmail() {
return email.get();
}
public void setEmail(String fName) {
email.set(fName);
}
public StringProperty emailProperty() {
return email ;
}
@Override
public int compareTo(Person o) {
return firstName.get().compareToIgnoreCase(o.getFirstName());
}
}
}
I have added my use case in question
我不知道您为什么需要这种行为。
一些建议:
table.getItems.add(index,element)
正如您在问题中首先提到的那样,而不是创建一个全新的列表并调用 table.getItems().setAll(newList)
。System.currentTimeMillis()
,否则当您报告平均 0.2 毫秒时,您的测量值非常不准确,因为您只是平均 0 毫秒和 1 毫秒值。因为我不认为这个问题有广泛的用处,所以我不会在这上面花更多的时间。
If it is really a issue I request you to do (file) it.... And am doing is because in swing based table (I can't post its code) it is much faster (in order of 0.2 ms in average)
我在 Java 8 早期访问版本中看到的交替行的闪烁是一个问题,我将尝试在一个更简单的程序中复制这个问题,并根据 JavaFX 问题跟踪器提交文件。
我认为这里没有任何关于性能的问题。是的,选择模型在 Java 7 中增加了一些(小的)开销,但在 Java 8 中,开销几乎察觉不到。对于该操作,我在 JavaFX for Java8 中测量的时间与您在 Swing 中测量的时间相同,为 0.2ms。因此,Java 8 的选择模型处理的平台实现已经进行了一些性能调整,我认为不需要进行任何进一步的调整。
also can you suggest me something on filtering
最好在新问题而不是评论中提出新问题。
不过,看看 Java 8 为此提供了什么。
有一个 FilteredList添加到 JavaFX for Java 8。另请参阅 Panemu's TiwulFX其中包括表格过滤功能(以及许多其他有用的功能),看看它是否适合您的应用程序。
一般方法建议
不要如此快速地向表中添加行,而是将传入的行插入分批处理并减少将它们添加到表中的频率(例如每四分之一秒)。用户不会关心表是否每秒更新四次而不是每秒更新 60 次。
次要观察
如果您想对场景进行非常频繁的更新,而不是使用具有关键帧和每 20 毫秒触发一次的事件处理程序的时间轴,请使用 AnimationTimer每当系统接收到处理脉冲时就会触发(默认情况下,脉冲以每秒 60 次的固定间隔发生;例如,每 16.666 毫秒)。这将使处理过程更加顺利,因为时间轴的 20 毫秒关键帧可能会错过一个脉冲并最终略微不均匀(尽管眼睛可能不会察觉到不均匀)。
关于javafx tableview 主动排序很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17165536/
我正在对 tableView 是否呈现单元格进行单元测试。 我发现 tableView.cellForRow(at:) 返回 nil,而 tableView.dataSource?tableView(
我有 Tableview 用于显示客户下的食品订单。其中包含水平 UIStackview。在 UIStackView UIStackview 中很少有一/两行标签和一个用于显示订单项的UITableV
我有 Viewcontroller,我在其中设置了 ScrollView 。在 scrollview 中,我有一个 tableview,它位于 Container 中,就在容器下方,当我将 table
我想在滚动时让我的第一个单元格始终位于 tableview 的顶部。 任何帮助都是可观的。提前致谢... 最佳答案 这是为 UITableView 创建标题 View 的方法 - (UIView *)
在我的应用程序中,我点击一行,它会在其下方展开另一行。我想生成一种随机颜色,当我单击一行时,行背景会变成该颜色,而它下面的展开行会变成相同的颜色。如何让行生成相同的随机颜色? 我创建了一个函数来生成随
我正在为这个问题苦苦挣扎,所以我需要你的帮助。基本上我已经编写了一个复杂的 TableView Controller (使用 NSFetchedResults 协议(protocol)等)并且已经在我
我正在使用 JavaFx 2.2。我遇到了一个问题,我无法在 TableView 列中放置不同的组件。例如我有两列 1) 回答 2) 答案类型 如果 AnswerType 包含“Multiple Ch
试图弄清楚如何在 javafx 2 中禁用表列的重新排序? 最佳答案 这是解决方案: tblView.getColumns().addListener(new ListChangeListener()
我一直在寻找有关将数据刷新到 tableview 的信息。我试图直接修改模型,但我遇到了一个错误。我修改了模型,但表格没有刷新,只有当我移动一列时,表格才会显示修改后的值。 为了给你展示一个例子(13
给定一个TableView,我需要检测单元格上的双击。 tableView.setOnMouseClicked(new EventHandler() { @Override publi
我成功创建了一个 TableView,其中将特定列分配给了数据模型类。该程序可以将 csv 文件解析为其中并在表中正确显示所有内容。在此阶段,滚动不是问题。 然后我想选择特定行并将它们发送到另一个表。
我尝试了所有方法来用数据填充 TableView。下一个代码在表中插入一个新行,但数据没有出现在表中。我试图为此找到解释,但没有成功。 请帮忙。我不知道怎么了。 在 controller.java 中
我尝试了所有方法来用数据填充 TableView。下一个代码在表中插入一个新行,但数据没有出现在表中。我试图为此找到解释,但没有成功。 请帮忙。我不知道怎么了。 在 controller.java 中
我有一个通过 Tableview 显示玩家的应用程序。用户可以“添加”一个新玩家并输入他的姓名、高度、体重、图片等...保存后将被添加到 Tableview 中。他们还可以点击每个玩家,然后将他们带到
对于大学,我必须编写一个小应用程序,其想法是创建一个小公式集合。这个概念是有一个类别列表,选择类别后您会收到一个公式列表。选择所需的公式后,您将看到公式计算器的 View 。 我正在努力获得第一个UI
如果我只加载一个 TableView ,我的 View 中必须有两个 TableView ,它工作正常。但是当我尝试使用下面的方法加载两个表格 View 时,它给出了以下异常。 未捕获异常“NSRan
我是 JavaFx 的新手,我正在尝试创建一个 TableView ,而 fxml 是使用场景生成器创建的。如果我运行该程序,该表不会获取值。我发现这个问题在某种程度上符合我的要求( javaFX 2
是否可以对 tableView 进行反向排序?我搜索了很多解决方案,但没有任何效果。 效果就像whatsapp聊天。 一个普通的tableView是: ---------- label 1 -----
我有一个有趣的问题。我有两个 TableView ,一个在另一个里面。我有一个结构,我想用它来将数据添加到我的 TableView 中。该结构有 2 个字符串项和另一个具有 3 个字符串项的结构的数组
我正在使用的方法 func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath
我是一名优秀的程序员,十分优秀!