在为JavaFX分配数据后,无法从TableView检索所有行

在为JavaFX分配数据后,无法从TableView检索所有行,java,javafx,tablerow,Java,Javafx,Tablerow,我有一个TableView,其中已经分配了一堆数据。在这之后,我想循环遍历所有行,检查一些条件,然后根据该条件使用CSS绘制每个行。为什么以下内容会产生IndexOutOfBoundsException?相反,我为什么不检索我想要的行?为什么我创建的数组是空的 int i = 0; for (Node n: tableViewPriority.lookupAll("TableRow")) { System.out.println(n);

我有一个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$0(TableViewController.java:202)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(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$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
JavaFX视图(表/树/列表/…)是虚拟的,只创建屏幕上显示的节点数。因此,无论我的域项目是如何推送TableRow对象的数量,推送的行数与您在屏幕上看到的行数相当(可能有一个视图缓冲区)

JavaFX视图(表/树/列表/…)都是虚拟的,只创建屏幕上看到的节点数。因此,无论“我的域项目”如何推送TableRow对象的数量,推送的行数与您在屏幕上看到的行数相当(可能存在视图缓冲区)

您都无法为表视图“检索行”
TableRow
实例仅为表中的可见项创建(而不是为表中滚动出视图的项创建),并且这些
TableRow
实例可用于其他项,例如,如果用户滚动表

因此,通常情况下,表中的大多数项目都没有与之关联的行,并且任何行显示的项目都可能发生更改,例如,当用户滚动表时。此外,可以在程序运行时的任意时间创建新的
TableRow
实例,例如,如果用户增加应用程序窗口的大小,并且为表分配了更多空间(因此可以看到更多项)

因此,您正在使用的方法——即使在您尝试执行发布的代码之前将数据添加到表视图中——根本不起作用。样式将仅应用于当前可见的行,如果用户滚动表格(或由于某些其他原因重用了这些行),则会突出显示错误的行(因为您的代码无法检查何时为新项目更新该行)

(此外,您不能保证查找将以正确的顺序返回表行实例。)

相反,请指定一个行工厂,在更新行的项目时更新行的样式:

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");
        }
    }
});
然后在外部CSS文件中,您可以执行以下操作:

。表格行单元格:低{
/*低优先级的样式…*。
}
无法为表视图“检索行”
TableRow
实例仅为表中的可见项创建(而不是为表中滚动出视图的项创建),并且这些
TableRow
实例可用于其他项,例如,如果用户滚动表

因此,通常情况下,表中的大多数项目都没有与之关联的行,并且任何行显示的项目都可能发生更改,例如,当用户滚动表时。此外,可以在程序运行时的任意时间创建新的
TableRow
实例,例如,如果用户增加应用程序窗口的大小,并且为表分配了更多空间(因此可以看到更多项)

因此,您正在使用的方法——即使在您尝试执行发布的代码之前将数据添加到表视图中——根本不起作用。样式将仅应用于当前可见的行,如果用户滚动表格(或由于某些其他原因重用了这些行),则会突出显示错误的行(因为您的代码无法检查何时为新项目更新该行)

(此外,您不能保证查找将以正确的顺序返回表行实例。)

相反,请指定一个行工厂,在更新行的项目时更新行的样式:

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");
        }
    }
});
然后在外部CSS文件中,您可以执行以下操作:

。表格行单元格:低{
/*低优先级的样式…*。
}
可观察列表数据=table.getItems();
对于(您的数据yd:数据){
//你的行动
}
可观察列表数据=table.getItems();
对于(您的数据yd:数据){
//你的行动
}

if(tableViewPriority.getItems().get(I)…)行中出现的异常(我假设该异常)指示
tableViewPriority.getItems()为空。但是,正如回答中所指出的,这种方法根本不起作用(即使您先填充表):一旦您开始滚动表视图,所有行都将没有正确的样式。使用
rowFactory
。是的,我尝试使用rowFactory,但检索行时遇到问题。我需要包含数据的行来应用条件。您不能“检索行”。这就是答案中提出的要点。您需要创建在调用
updateItem()
方法时更新其样式的行。您应该显示您使用行工厂所做的尝试。异常(我假设发生在
行中,如果(tableViewPriority.getItems().get(I)…)
)指示
tableViewPriority.getItems()
为空。但是,正如回答中所指出的,这种方法根本不起作用(即使您先填充表):一旦您开始滚动表视图,所有行都将没有正确的样式。使用
rowFactory
。是的,我尝试使用rowFactory,但检索行时遇到问题。我需要包含数据的行来应用条件。您不能“检索行”。这就是答案中提出的要点。您需要创建在调用
updateItem()
方法时更新其样式的行。您应该展示您使用行工厂所做的尝试。是的,使用伪状态是正确的方法,也是最有效的方法!是的,使用伪状态是正确的方法,也是最有效的方法!请详细说明这是解决方案的原因。请
ObservableList<yourData> data =table.getItems();

for(yourData yd : data) {
    //your action
}