JavaFX TreeView:TreeCells的访问列表(JavaFX TreeView: Access list of TreeCells)

编程入门 行业动态 更新时间:2024-10-28 10:36:28
JavaFX TreeView:TreeCells的访问列表(JavaFX TreeView: Access list of TreeCells)

我试图从TreeView中获取当前存在的TreeCells的列表。 我目前的尝试看起来像这样:

private Set<MyTreeCell> getMyTreeCells(){ try { @SuppressWarnings("unchecked") Field f = ((VirtualContainerBase<TreeView<myNode>, TreeViewBehavior<myNode>, MyTreeCell>) myTreeView.skinProperty().get()).getClass().getDeclaredField("flow"); f.setAccessible(true); @SuppressWarnings("unchecked") Field g = ((VirtualFlow<MyTreeCell>) f.get(((VirtualContainerBase<TreeView<myNode>, TreeViewBehavior<myNode>, ProofTreeCell>) proofTreeView.skinProperty().get()))).getClass().getDeclaredField("cells"); g.setAccessible(true); @SuppressWarnings("unchecked") ArrayLinkedList<MyTreeCell> l = (ArrayLinkedList<MyTreeCell>) g.get(((VirtualFlow<MyTreeCell>) f.get(((TreeViewSkin<myNode>) myTreeView.skinProperty().get())))); Set<myTreeCell> s = new HashSet<>(); s.addAll(l); return s; } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }

不幸的是它会抛出java.lang.NoSuchFieldException: flow 。 但为什么? 显然,字段flow存在于类VirtualContainerBase中。

请注意,我只是为了好玩而写这个,而不是实际用于生产代码。 我已经有了一个更清洁的问题解决方案。

I am trying to get a list of the currently existing TreeCells out of my TreeView. My current attempt looks like this:

private Set<MyTreeCell> getMyTreeCells(){ try { @SuppressWarnings("unchecked") Field f = ((VirtualContainerBase<TreeView<myNode>, TreeViewBehavior<myNode>, MyTreeCell>) myTreeView.skinProperty().get()).getClass().getDeclaredField("flow"); f.setAccessible(true); @SuppressWarnings("unchecked") Field g = ((VirtualFlow<MyTreeCell>) f.get(((VirtualContainerBase<TreeView<myNode>, TreeViewBehavior<myNode>, ProofTreeCell>) proofTreeView.skinProperty().get()))).getClass().getDeclaredField("cells"); g.setAccessible(true); @SuppressWarnings("unchecked") ArrayLinkedList<MyTreeCell> l = (ArrayLinkedList<MyTreeCell>) g.get(((VirtualFlow<MyTreeCell>) f.get(((TreeViewSkin<myNode>) myTreeView.skinProperty().get())))); Set<myTreeCell> s = new HashSet<>(); s.addAll(l); return s; } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }

Unfortunately it throws java.lang.NoSuchFieldException: flow. But why? Clearly the Field flow exists in the Class VirtualContainerBase.

Please note that I only wrote this for fun, and not to actually be used in productive code. I already have a cleaner solution for the problem.

最满意答案

VirtualContainerBase声明了flow ,但myTreeView.skinProperty().get().getClass()不返回VirtualContainerBase.class ,它返回TreeViewSkin.class 。 由于getDeclaredField()仅返回在该类中声明的字段,而不返回继承的字段,因此您将获得异常。

我想你可以做到

Field f = VirtualContainerBase.class.getDeclaredField("flow"); Field g = VirtualFlow.class.getDeclaredField("cells");

你也可以消除你的大部分演员,如下例所示:

import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.sun.javafx.scene.control.skin.VirtualContainerBase; import com.sun.javafx.scene.control.skin.VirtualFlow; import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class GetTreeCellsByReflection extends Application { @SuppressWarnings({ "restriction", "unchecked" }) @Override public void start(Stage primaryStage) { TreeView<Integer> tree = createRandomTree(100); Button findCells = new Button("Find cells"); findCells.setOnAction(e -> { try { Field flowField = VirtualContainerBase.class.getDeclaredField("flow"); flowField.setAccessible(true); Field cellsField = VirtualFlow.class.getDeclaredField("cells"); cellsField.setAccessible(true); Object flow = flowField.get(tree.getSkin()); ((Iterable<TreeCell<?>>) cellsField.get(flow)).forEach(System.out::println);; } catch (Exception exc) { exc.printStackTrace(); } }); BorderPane root = new BorderPane(tree); BorderPane.setAlignment(findCells, Pos.CENTER); BorderPane.setMargin(findCells, new Insets(5)); root.setBottom(findCells); Scene scene = new Scene(root, 600, 600); primaryStage.setScene(scene); primaryStage.show(); } private TreeView<Integer> createRandomTree(int numItems) { Random rng = new Random(); TreeItem<Integer> root = new TreeItem<>(0); List<TreeItem<Integer>> items = new ArrayList<>(); items.add(root); for (int i = 1 ; i < numItems ; i++) { TreeItem<Integer> item = new TreeItem<>(i); items.get(rng.nextInt(items.size())).getChildren().add(item); items.add(item); } return new TreeView<>(root); } public static void main(String[] args) { launch(args); } }

VirtualContainerBase declares flow, but myTreeView.skinProperty().get().getClass() does not return VirtualContainerBase.class, it returns TreeViewSkin.class. Since getDeclaredField() only returns fields declared in that class, not inherited fields, you get the exception.

I think you can just do

Field f = VirtualContainerBase.class.getDeclaredField("flow"); Field g = VirtualFlow.class.getDeclaredField("cells");

You can also eliminate much of the casting you have, as in this example:

import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.sun.javafx.scene.control.skin.VirtualContainerBase; import com.sun.javafx.scene.control.skin.VirtualFlow; import javafx.application.Application; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TreeCell; import javafx.scene.control.TreeItem; import javafx.scene.control.TreeView; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class GetTreeCellsByReflection extends Application { @SuppressWarnings({ "restriction", "unchecked" }) @Override public void start(Stage primaryStage) { TreeView<Integer> tree = createRandomTree(100); Button findCells = new Button("Find cells"); findCells.setOnAction(e -> { try { Field flowField = VirtualContainerBase.class.getDeclaredField("flow"); flowField.setAccessible(true); Field cellsField = VirtualFlow.class.getDeclaredField("cells"); cellsField.setAccessible(true); Object flow = flowField.get(tree.getSkin()); ((Iterable<TreeCell<?>>) cellsField.get(flow)).forEach(System.out::println);; } catch (Exception exc) { exc.printStackTrace(); } }); BorderPane root = new BorderPane(tree); BorderPane.setAlignment(findCells, Pos.CENTER); BorderPane.setMargin(findCells, new Insets(5)); root.setBottom(findCells); Scene scene = new Scene(root, 600, 600); primaryStage.setScene(scene); primaryStage.show(); } private TreeView<Integer> createRandomTree(int numItems) { Random rng = new Random(); TreeItem<Integer> root = new TreeItem<>(0); List<TreeItem<Integer>> items = new ArrayList<>(); items.add(root); for (int i = 1 ; i < numItems ; i++) { TreeItem<Integer> item = new TreeItem<>(i); items.get(rng.nextInt(items.size())).getChildren().add(item); items.add(item); } return new TreeView<>(root); } public static void main(String[] args) { launch(args); } }

更多推荐

本文发布于:2023-07-23 01:21:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1225617.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:列表   TreeView   JavaFX   TreeCells   list

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!