JavaFx,如何正确覆盖两者:树 Table 视图中的 getChildren() 和 getChildren().add(newNode)
JavaFx, how to correctly override both : getChildren() and getChildren().add(newNode) in a Tree Table View
在一个使用非常广泛的 TreeTableView
s 的应用程序中,我发现每次将 child 添加到此树时都需要触发代码。
我的第一个方法是 'encapsulate' 方法中的 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)
方法。
我做了很多研究,最后尝试制作:
- child人的并行列表。
- 覆盖“add(...)”
TreeItem
的 getChildren()
返回的列表
getChildren()
的 Overriden 部分的灵感来自于
https://docs.oracle.com/javafx/2/api/javafx/scene/control/TreeItem.html
在 class 中创建并行 LIST(准确地说是 FXCollections.observableArrayList()
)的部分是在 PDF 中提出的,我不能回头找一位印度老师练习他的 JavaFx class.
下面的代码只需要复制,所以我已经包含在 'main' class 中,所有底层 classes...我知道这不是最佳实践,但是为了让您尽可能轻松地制作代码 运行,我决定这样做......如果您认为照常制作更好,请告诉我:1 Class = 1 个文件。
问题:
我遇到的问题通过在 2 运行s 中使用 MCE 来说明(一个复选框会更好吗?):
对部分代码进行注释。然后运行。然后触发按钮 -->
Un-commenting 相同的部分。然后运行。然后触发按钮 -->
表现形式 1:树
所以在这两种情况下,我的第一个 children 列表都存在...它们在 ROOT 树项目下,但是:当通过自定义 ObservableList 时,它们没有显示在树中,在 ROOT 下.
据我所知,TreeTableView 的机制依赖于对 TreeItem 列表的特定调用:children,可能我在那里遗漏了一些东西......因为我制作了一个并行 LIST因此不被称为......有点......做了一些研究和实验,但到目前为止没有运气:-(.
是不是因为:
- TreeTableView 中缺少某些内容:CellValueFactory / CellFactory / TreeItems / ...
- 我的 ObservableList 有问题:我应该实施另一个覆盖/使用了错误的上升/应该 'implement' 和 'extend' 而不是 'extend'?
表现形式 2:Children / Parent
我已经破解了children/parent!这也与我尝试构建并行LIST并进行自定义getChildren()
有关。我想应该是 super.getChildren()
的自定义,但话又说回来,尝试了很多方法都没有成功。如果是这样,我得到的不是我定制的 LIST,而是原始(正确)的。
将不胜感激。
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);
}
}
有时,最好只是仔细观察并从头开始重新启动整个体系结构。这导致了我的情况下可能的最佳答案之一......我希望......它运作良好!
覆盖 getChildren.add(...)
的方法在这种情况下是错误的方法。
正确的方向是 events,在本例中是 addEventHandler
:
https://docs.oracle.com/javafx/2/api/javafx/scene/control/TreeItem.html#addEventHandler(javafx.event.EventType,%20javafx.event.EventHandler)
并且通过使用 TreeItem.childrenModificationEvent()
添加到树的每个元素,最终得到想要的结果非常简单:我的 TreeTableView 的任何添加都通过我的个性化代码。
这是实施了解决方案的 MCE:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.EventHandler;
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 CustomedTypedTreeTableSample2 extends Application {
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);
}
}
private final class TreeItemPlaylist extends TreeItem<TreeTableRowPlaylist> {
// private boolean isFirstTimeChildren = true;
private TreeItemPlaylist(TreeTableRowPlaylist treeTableRowPlaylist) {
super(treeTableRowPlaylist);
addEventHandler(TreeItem.childrenModificationEvent(), this::childrenModification);
// Same code in a 'anonymous' implementation :
// addEventHandler(TreeItem.childrenModificationEvent(), new EventHandler<TreeModificationEvent<TreeTableRowPlaylist>>() {
// @Override
// public void handle(TreeModificationEvent<TreeTableRowPlaylist> event) {
// childrenModification(event);
// }
// });
}
private void childrenModification(TreeModificationEvent<TreeTableRowPlaylist> event) {
if (event.wasAdded()) {
for (TreeItem<TreeTableRowPlaylist> item : event.getAddedChildren()) {
System.out.println("Node " + item.getValue().getName() + " has been added.");
}
}
}
}
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);
}
@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 tree 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();
}
}
在一个使用非常广泛的 TreeTableView
s 的应用程序中,我发现每次将 child 添加到此树时都需要触发代码。
我的第一个方法是 'encapsulate' 方法中的 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)
方法。
我做了很多研究,最后尝试制作:
- child人的并行列表。
- 覆盖“add(...)”
TreeItem
的
getChildren()
返回的列表
getChildren()
的 Overriden 部分的灵感来自于
https://docs.oracle.com/javafx/2/api/javafx/scene/control/TreeItem.html
在 class 中创建并行 LIST(准确地说是 FXCollections.observableArrayList()
)的部分是在 PDF 中提出的,我不能回头找一位印度老师练习他的 JavaFx class.
下面的代码只需要复制,所以我已经包含在 'main' class 中,所有底层 classes...我知道这不是最佳实践,但是为了让您尽可能轻松地制作代码 运行,我决定这样做......如果您认为照常制作更好,请告诉我:1 Class = 1 个文件。
问题: 我遇到的问题通过在 2 运行s 中使用 MCE 来说明(一个复选框会更好吗?):
对部分代码进行注释。然后运行。然后触发按钮 -->
Un-commenting 相同的部分。然后运行。然后触发按钮 -->
表现形式 1:树
所以在这两种情况下,我的第一个 children 列表都存在...它们在 ROOT 树项目下,但是:当通过自定义 ObservableList 时,它们没有显示在树中,在 ROOT 下.
据我所知,TreeTableView 的机制依赖于对 TreeItem 列表的特定调用:children,可能我在那里遗漏了一些东西......因为我制作了一个并行 LIST因此不被称为......有点......做了一些研究和实验,但到目前为止没有运气:-(.
是不是因为:
- TreeTableView 中缺少某些内容:CellValueFactory / CellFactory / TreeItems / ...
- 我的 ObservableList 有问题:我应该实施另一个覆盖/使用了错误的上升/应该 'implement' 和 'extend' 而不是 'extend'?
表现形式 2:Children / Parent
我已经破解了children/parent!这也与我尝试构建并行LIST并进行自定义getChildren()
有关。我想应该是 super.getChildren()
的自定义,但话又说回来,尝试了很多方法都没有成功。如果是这样,我得到的不是我定制的 LIST,而是原始(正确)的。
将不胜感激。
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);
}
}
有时,最好只是仔细观察并从头开始重新启动整个体系结构。这导致了我的情况下可能的最佳答案之一......我希望......它运作良好!
覆盖 getChildren.add(...)
的方法在这种情况下是错误的方法。
正确的方向是 events,在本例中是 addEventHandler
:
https://docs.oracle.com/javafx/2/api/javafx/scene/control/TreeItem.html#addEventHandler(javafx.event.EventType,%20javafx.event.EventHandler)
并且通过使用 TreeItem.childrenModificationEvent()
添加到树的每个元素,最终得到想要的结果非常简单:我的 TreeTableView 的任何添加都通过我的个性化代码。
这是实施了解决方案的 MCE:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.event.EventHandler;
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 CustomedTypedTreeTableSample2 extends Application {
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);
}
}
private final class TreeItemPlaylist extends TreeItem<TreeTableRowPlaylist> {
// private boolean isFirstTimeChildren = true;
private TreeItemPlaylist(TreeTableRowPlaylist treeTableRowPlaylist) {
super(treeTableRowPlaylist);
addEventHandler(TreeItem.childrenModificationEvent(), this::childrenModification);
// Same code in a 'anonymous' implementation :
// addEventHandler(TreeItem.childrenModificationEvent(), new EventHandler<TreeModificationEvent<TreeTableRowPlaylist>>() {
// @Override
// public void handle(TreeModificationEvent<TreeTableRowPlaylist> event) {
// childrenModification(event);
// }
// });
}
private void childrenModification(TreeModificationEvent<TreeTableRowPlaylist> event) {
if (event.wasAdded()) {
for (TreeItem<TreeTableRowPlaylist> item : event.getAddedChildren()) {
System.out.println("Node " + item.getValue().getName() + " has been added.");
}
}
}
}
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);
}
@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 tree 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();
}
}