【发布时间】:2021-10-26 10:34:16
【问题描述】:
在一个非常广泛地使用TreeTableViews 的应用程序中,我发现每次将一个孩子添加到这棵树时都需要触发一个代码。
我的第一种方法是将myTree.getChildren().add(...)“封装”在一个方法中,例如:
public boolean addToChildren(TreeItemPlaylist tritPlaylist) {
boolean resAdd = false;
resAdd = getChildren().add(tritPlaylist);
[... personalized code which might affect the resAdd ...]
return resAdd;
}
这仍然使getChildren().add(...) 可以访问,因此可以绕过我的个性化代码。
我正在寻找更清洁的东西,并且一直试图覆盖 TreeTableView 中 getChildren() 的 add(newNode) 方法。
我做了相当多的研究,最终尝试做:
- 子项的并行列表。然后将可以访问
- 是否覆盖了'add(...)
- 而该列表由
getChildren()的TreeItem返回
getChildren() 的 Overriden 部分的灵感来自于
https://docs.oracle.com/javafx/2/api/javafx/scene/control/TreeItem.html
在一个我找不到的印度老师的 PDF 中建议了在一个将扩展 SimpleListProperty<T> 的类中制作并行列表(准确地说是 FXCollections.observableArrayList())的部分,作为练习他的 JavaFx 类。
只需复制以下代码,因此我将所有底层类都包含在“主”类中...我知道这不是最佳实践,但为了使其尽可能简单你让代码运行,我决定这样做......请告诉我你是否认为像往常一样让它更好:1 Class = 1 File。
问题: 通过在 2 次运行中使用 MCE 来说明我遇到的问题(复选框会更好吗?):
表现形式 1:树
所以在这两种情况下,我的 FIRST 子列表都存在...它们位于 ROOT 树项下,但是:当通过自定义的 ObservableList 时,它们不会显示在树中,在 ROOT 下。
据我所知,TreeTableView 的机制依赖于对 TreeItem 列表的特定调用:孩子,并且可能我在那里遗漏了一些东西......因为我创建了一个并行列表,因此没有被调用......有点...做了一些研究和实验,但到目前为止还没有运气:-(。
是不是因为:
- TreeTableView 上缺少某些内容:CellValueFactory / CellFactory / TreeItems / ...
- 我的 ObservableList 有问题:我应该实施另一个覆盖/使用了错误的升序/应该“实施”和“扩展”而不是“扩展”?
表现 2:孩子/父母
我破坏了孩子/父母!这也与我尝试构建并行 LIST 并制作自定义 getChildren() 的事实有关。我想应该是super.getChildren()的自定义,但话又说回来,尝试了很多方法都没有成功。如果是这样,我得到的不是我的自定义列表,而是原始(正确)列表。
我们将不胜感激。
MCE:
package overrides;
import javafx.application.Application;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableRow;
import javafx.scene.control.TreeTableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CustomedTypedTreeTableSample extends Application {
public final class ObservableListOfTreeItemPlaylist<T> extends SimpleListProperty<T> {
ObservableListOfTreeItemPlaylist() {
super(FXCollections.observableArrayList());
}
@Override
public boolean add(T element) {
System.out.println("Adding an element");
return super.add(element);
}
}
public class TreeItemPlaylist extends TreeItem<TreeTableRowPlaylist> {
private ObservableListOfTreeItemPlaylist<TreeItem<TreeTableRowPlaylist>> playlistItems = new ObservableListOfTreeItemPlaylist<>();
public TreeItemPlaylist(TreeTableRowPlaylist treeTableRow) {
super(treeTableRow);
}
////////////////////////
// COMMENT / UNCOMMENT the next overridden method to see my problem
//
// When commenting : - GUI tree is filled with the correct children. All is fine... but, of course, no customized 'add(...'
// - When printing to console the children of root : All branches and children are there !
//
// When NOT commenting : - The overridden 'add(T element)' of class ObservableListOfTreeItemPlaylist is fired...
// - GUI tree is left with only the ROOT element
// - When printing to console only the first children of root are there ! But hey... they are there on the console, but not in the GUI !
@Override
public ObservableListOfTreeItemPlaylist<TreeItem<TreeTableRowPlaylist>> getChildren() {
return playlistItems;
}
////////////////////////
}
public class TreeTableRowPlaylist extends TreeTableRow<TreeTableRowPlaylist> {
// Initialized during constructor
private SimpleStringProperty name;
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public SimpleStringProperty nameProperty() {
return name;
}
public TreeTableRowPlaylist(String name) {
super();
this.name = new SimpleStringProperty(name);
}
}
@SuppressWarnings ("unchecked")
@Override
public void start(Stage primaryStage) {
///// TreeTableView basics
// Tree table view
TreeTableView<TreeTableRowPlaylist> tableView = new TreeTableView<>();
// Column for the name
TreeTableColumn<TreeTableRowPlaylist, String> nameColumn = new TreeTableColumn<>("Name");
nameColumn.setCellValueFactory(param -> param.getValue().getValue().nameProperty());
// Add column
tableView.getColumns().addAll(nameColumn);
///// Dummy tree building
tableView.setRoot(new TreeItemPlaylist(new TreeTableRowPlaylist("ROOT")));
tableView.getRoot().getChildren().add(new TreeItemPlaylist(new TreeTableRowPlaylist("Playlist Leaf 1")));
tableView.getRoot().getChildren().add(new TreeItemPlaylist(new TreeTableRowPlaylist("Playlist Leaf 2")));
TreeItemPlaylist aTreeBranchA = new TreeItemPlaylist(new TreeTableRowPlaylist("Playlist Branch A"));
aTreeBranchA.getChildren().add(new TreeItemPlaylist(new TreeTableRowPlaylist("Playlist Leaf A.1")));
aTreeBranchA.getChildren().add(new TreeItemPlaylist(new TreeTableRowPlaylist("Playlist Leaf A.2")));
tableView.getRoot().getChildren().add(aTreeBranchA);
///// Testing if overriding is working
// button to get the list of children
Button display = new Button("Print out children list to console");
display.setOnAction(event -> tableView.getRoot().getChildren().forEach(playlist -> printChildrenToConsole(playlist)));
///// Setting the GUI
VBox vbox = new VBox(0, tableView, display);
Scene scene = new Scene(vbox);
primaryStage.setScene(scene);
primaryStage.show();
}
private void printChildrenToConsole(TreeItem<TreeTableRowPlaylist> playlist) {
System.out.println(playlist.getValue().getName());
if (!playlist.isLeaf()) {
playlist.getChildren().forEach(childPlaylist -> printChildrenToConsole(childPlaylist));
}
}
public static void main(String[] args) {
launch(args);
}
}
【问题讨论】:
-
你为什么要这样做?您可以使用您的解释编辑问题。此外,通常最好提供minimal reproducible example,但在这种情况下,即使提供了完整的可编译示例,我也不希望您在没有真正令人信服的理由的情况下获得大量帮助。
-
mipa 已经在他的prior answer 中提供了一个合理的策略,为什么不遵循这个策略呢?即“重写 JavaFx TreeItem getChildren 是否添加了一个好主意?” -> 可能不会。
-
你好@jewelsea,谢谢你的提问。我的另一个问题没有很好地表述。试图删除它但不可能:建议的包装(我从一开始就使用,正如您在我的问题的 cmets 中看到的那样)是我调查的解决方法,而不是正确的解决方案。我想使用继承做得更好并改进我的代码。我认为戴帽子会使问题变得更重,所以我直奔主题。我将对其进行编辑和上下文化。
-
很公平,我没有对它投反对票,而是对你的努力投了赞成票。我确实认为我以前的 cmets 就如何改进这个问题提供了一些建议。我想说如果推理很明显,只是在没有上下文的情况下提出问题是可以的,但在这种情况下需要上下文,它确实有点像xy problem,如果是这种情况,上下文可以帮助澄清.投票通常是关于问题是否对其他人有用,而不仅仅是提问者,人们经常投票赞成,因为它对他们有用。
-
“我想做得更好并改进我的代码,使用继承。” -> 有时(通常?)继承不会改进代码。这不是通常详细讨论此类事情的地方,但请参阅:Inheritance vs. Aggregation 以供参考。经验丰富的开发人员 (mipa) 查看了您的示例并建议聚合而不是继承,这意味着聚合可能是首选方法。但是,由于您最了解自己的问题领域,因此您的方法可能也有优点。
标签: inheritance javafx treeview overriding treetable