数据分配 JavaFX 后无法从 TableView 检索所有行
Cannot retrieve all rows from TableView after data assigned JavaFX
我有一个 TableView,其中已经分配了一堆数据。在此之后,我想遍历所有行,检查一些条件,然后根据该条件用 CSS 绘制每一行。为什么以下会产生 IndexOutOfBoundsException?相反,为什么我不检索我想要的行?为什么我创建的数组是空的?
int i = 0;
for (Node n: tableViewPriority.lookupAll("TableRow")) {
System.out.println(n);
if (n instanceof TableRow) {
TableRow row = (TableRow) n;
System.out.println(row);
if (tableViewPriority.getItems().get(i).getPriority().equals("Low")) {
row.getStyleClass().add("tableViewGreen");
}
i++;
if (i == tableViewPriority.getItems().size())
break;
}
}
异常:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
at app.controller.TableViewController.populateTable(TableViewController.java:356)
at app.controller.TableViewController.organizeTable(TableViewController.java:318)
at app.controller.TableViewController.assignTicketsToTable(TableViewController.java:236)
at app.controller.TableViewController.lambda$null[=11=](TableViewController.java:202)
at com.sun.javafx.application.PlatformImpl.lambda$null3(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater4(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null8(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
JavaFX-Views (Table/Tree/List/...) 是虚拟的,只创建与屏幕上看到的一样多的节点。因此,无论我的 Domain-Items 如何将 TableRow 对象的数量推送到与您在屏幕上看到的行数相当的数量(可能有视图缓冲区)
您无法 "retrieve the rows" 获得 table 视图。 TableRow
实例仅为 table 中的 visible 项创建(不适用于 table 中滚出视图的项),并且这些 TableRow
实例可以重复用于其他项目,例如,如果用户滚动 table。
因此,通常 table 中的大多数项目都没有与其关联的行,并且任何行显示的项目都可能发生变化,例如当用户滚动 table 时。此外,当程序 运行 时,可以在任意时间创建新的 TableRow
实例,例如,如果用户增加应用程序的大小 window 并且更多 space分配给 table(因此可以看到更多项目)。
因此您使用的方法 - 即使在您尝试执行您发布的代码之前将数据添加到 table 视图 - 也根本行不通。样式只会应用于当前可见的行,并且如果用户滚动 table(或由于某些其他原因重复使用这些行),则会突出显示错误的行(因为您的代码无法检查何时该行已更新为新项目)。
(此外,您无法保证查找会以正确的顺序 return table 行实例。)
而是指定一个行工厂,在更新行的项目时更新行的样式:
tableViewPriority.setRowFactory(tv -> new TableRow<SomeClass>() {
@Override
protected void updateItem(SomeClass item, boolean empty) {
super.updateItem(item, empty);
if (item!=null && "Low".equals(item.getPriority())) {
if (! getStyleClass().contains("tableViewGreen")) {
getStyleClass().add("tableViewGreen");
}
} else {
getStyleClass().remove("tableViewGreen");
}
}
});
显然用 table 显示的任何类型替换 SomeClass
。
请注意,使用 CSS PseudoClass 而不是普通的 CSS class:
可能更简洁
PseudoClass low = PseudoClass.getPseudoClass("low");
tableViewPriority.setRowFactory(tv -> new TableRow<SomeClass>() {
@Override
protected void updateItem(SomeClass item, boolean empty) {
super.updateItem(item, empty);
pseudoClassStateChanged(low, item!=null && "Low".equals(item.getPriority()));
}
});
然后在你的外部 CSS 文件中你可以做:
.table-row-cell:low {
/* styles for low priority... *.
}
ObservableList<yourData> data =table.getItems();
for(yourData yd : data) {
//your action
}
我有一个 TableView,其中已经分配了一堆数据。在此之后,我想遍历所有行,检查一些条件,然后根据该条件用 CSS 绘制每一行。为什么以下会产生 IndexOutOfBoundsException?相反,为什么我不检索我想要的行?为什么我创建的数组是空的?
int i = 0;
for (Node n: tableViewPriority.lookupAll("TableRow")) {
System.out.println(n);
if (n instanceof TableRow) {
TableRow row = (TableRow) n;
System.out.println(row);
if (tableViewPriority.getItems().get(i).getPriority().equals("Low")) {
row.getStyleClass().add("tableViewGreen");
}
i++;
if (i == tableViewPriority.getItems().size())
break;
}
}
异常:
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at com.sun.javafx.collections.ObservableListWrapper.get(ObservableListWrapper.java:89)
at app.controller.TableViewController.populateTable(TableViewController.java:356)
at app.controller.TableViewController.organizeTable(TableViewController.java:318)
at app.controller.TableViewController.assignTicketsToTable(TableViewController.java:236)
at app.controller.TableViewController.lambda$null[=11=](TableViewController.java:202)
at com.sun.javafx.application.PlatformImpl.lambda$null3(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater4(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null8(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
JavaFX-Views (Table/Tree/List/...) 是虚拟的,只创建与屏幕上看到的一样多的节点。因此,无论我的 Domain-Items 如何将 TableRow 对象的数量推送到与您在屏幕上看到的行数相当的数量(可能有视图缓冲区)
您无法 "retrieve the rows" 获得 table 视图。 TableRow
实例仅为 table 中的 visible 项创建(不适用于 table 中滚出视图的项),并且这些 TableRow
实例可以重复用于其他项目,例如,如果用户滚动 table。
因此,通常 table 中的大多数项目都没有与其关联的行,并且任何行显示的项目都可能发生变化,例如当用户滚动 table 时。此外,当程序 运行 时,可以在任意时间创建新的 TableRow
实例,例如,如果用户增加应用程序的大小 window 并且更多 space分配给 table(因此可以看到更多项目)。
因此您使用的方法 - 即使在您尝试执行您发布的代码之前将数据添加到 table 视图 - 也根本行不通。样式只会应用于当前可见的行,并且如果用户滚动 table(或由于某些其他原因重复使用这些行),则会突出显示错误的行(因为您的代码无法检查何时该行已更新为新项目)。
(此外,您无法保证查找会以正确的顺序 return table 行实例。)
而是指定一个行工厂,在更新行的项目时更新行的样式:
tableViewPriority.setRowFactory(tv -> new TableRow<SomeClass>() {
@Override
protected void updateItem(SomeClass item, boolean empty) {
super.updateItem(item, empty);
if (item!=null && "Low".equals(item.getPriority())) {
if (! getStyleClass().contains("tableViewGreen")) {
getStyleClass().add("tableViewGreen");
}
} else {
getStyleClass().remove("tableViewGreen");
}
}
});
显然用 table 显示的任何类型替换 SomeClass
。
请注意,使用 CSS PseudoClass 而不是普通的 CSS class:
可能更简洁PseudoClass low = PseudoClass.getPseudoClass("low");
tableViewPriority.setRowFactory(tv -> new TableRow<SomeClass>() {
@Override
protected void updateItem(SomeClass item, boolean empty) {
super.updateItem(item, empty);
pseudoClassStateChanged(low, item!=null && "Low".equals(item.getPriority()));
}
});
然后在你的外部 CSS 文件中你可以做:
.table-row-cell:low {
/* styles for low priority... *.
}
ObservableList<yourData> data =table.getItems();
for(yourData yd : data) {
//your action
}