2017-06-16 60 views
0

我有一个TableView,其中有一堆已分配给它的数据。在此之后,我想遍历所有行,检查一些条件,然后根据该条件使用CSS为每个条件绘制。为什么以下产生IndexOutOfBoundsException?相反,为什么我不检索我想要的行?为什么我创建的数组是空的?无法从数据分配后从TableView中检索所有行JavaFX

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) 
+0

例外(我假设(tableViewPriority.getItems()。get(i)...)')表示'tableViewPriority.getItems()'是空的。但正如答案中所指出的那样,这种方法根本不起作用(即使您先填充表格):一旦开始滚动表格视图,没有任何行将具有正确的样式。使用'rowFactory'。 –

+0

是的,我尝试过使用RowFactory,但我无法检索行。我需要包含数据的行来应用条件。 – santafebound

+0

你不能“检索行”。答案就是这一点。您需要创建行,以便在调用updateItem()方法时更新其样式。您应该显示您使用行工厂进行的尝试。 –

回答

2

您无法“检索行”一张桌子视图。 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"); 
     } 
    } 
}); 

显然用您的表显示的任何类型替换SomeClass

注意这可能是清洁剂使用,而不是一个简单的CSS类CSS伪类,:

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... *. 
} 
+0

是的,使用pseudoState是正确的方法,也是性能最好的方法! – tomsontom

1

JavaFX的视图(表/树/列表/ ...)是虚拟的,只作为创建屏幕上看到尽可能多的节点。因此,无论您的Domain-Items如何将您在屏幕上看到的相同数量的行中推送的TableRow对象的数量(可能存在视图的缓冲区)