我的代码收到以下错误。
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: javafx.scene.Group cannot be cast to javafx.scene.control.TreeCell
源代码
private TreeItem getClickedTreeItem(EventTarget eventTarget){
TreeItem clickedTreeItem = null;
if(eventTarget instanceof TreeCellSkin){
clickedTreeItem = (TreeItem) ((TreeCell) ((TreeCellSkin)eventTarget).getParent()).getTreeItem();
}else if(eventTarget instanceof LabeledText){
clickedTreeItem = (TreeItem) ((TreeCell) ((LabeledText)eventTarget).getParent().getParent()).getTreeItem();
}else if(eventTarget instanceof ImageView){
clickedTreeItem = (TreeItem) ((TreeCell) ((ImageView)eventTarget).getParent().getParent()).getTreeItem();
}
return clickedTreeItem;
}
控制台显示以下行:
clickedTreeItem = (TreeItem) ((TreeCell) ((ImageView)eventTarget).getParent().getParent()).getTreeItem();
这是可与Java 6一起使用的旧代码,但使用Java8却给出了上述异常?
现在是什么原因导致
ClassCastException
,以及如何针对Java8修复它? 最佳答案
当前代码很脆弱,因为它依赖TreeCell
的内部结构。另外,TreeCellSkin
1和LabeledText
都是内部类。内部代码如有更改,恕不另行通知,也无需考虑第三方对此的依赖。由于这在Java 6中有效,但在Java 8中无效,因此我只能假定ImageView
的祖父母在这两个版本之间从TreeCell
变为了Group
。
要解决此问题,您可以查看实现并查看需要执行的操作,以便再次到达TreeCell
,但这并不能真正解决问题。 EventTarget
的使用对我说,此代码是在实现时没有完全理解JavaFX中事件处理的工作原理。从此代码的明显目标出发,您应该使用事件的来源,而不是目标。在JavaFX中,事件的来源始终是当前处理了EventHandler
的Event
被添加到的对象。换句话说,如果您将EventHandler
添加到TreeCell
中,则源将是TreeCell
。使用源代码,并假设将EventHandler
添加到TreeCell
,您可以简单地执行以下操作:
TreeItem<?> item = ((TreeCell<?>) event.getSource()).getTreeItem();
当然,如果您将
EventHandler
添加到TreeCell
中,则您可能无需打扰源代码,因为您可以直接访问TreeCell
。例如:TreeView<String> treeView = new TreeView<>();
treeView.setCellFactory(tv -> {
TreeCell<String> cell = new TreeCell<>(); // or some custom implementation
cell.setOnMouseClicked(event -> {
TreeItem<String> item = cell.getTreeItem();
// do something with item...
});
return cell;
});
1.
TreeCellSkin
连同许多(所有?)外观实现一起成为JavaFX 9中的公共API。它们是javafx.scene.control.skin
包的一部分。2.还有更多的东西,但这超出了此答案的范围。
关于java - JavaFX中的ClassCastException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53718939/