Reputation: 67
i have a treeview which look like this
Let suppose 1,2,3 are called root and 4,5,6,7 are called coordinates. Each coordinate generate 2 rectangles which are shown horizontally on roots. here is code
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import java.util.HashMap;
import java.util.Map;
public class Main extends Application {
private static int rootNr = 0;
private static int coordinateNr = 0;
public static void main(String[] args) {
launch(args);
}
static final Map<TreeItem<String>, BorderPane> map = new HashMap<>();
@Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
TreeItem<String> tree = new TreeItem<>("Main System");
TreeItem<String> item1 = new TreeItem<>("Roots");
TreeView<String> treeView = new TreeView<>(tree);
treeView.setOnMouseClicked((event) -> {
TreeItem<String> treeItem = treeView.getSelectionModel().getSelectedItem();
if (treeItem.getChildren().stream().anyMatch(child -> child.getValue().startsWith("C"))) {
root.setCenter(getRootsPanel(treeItem.getValue()));
}else {
root.setCenter(map.get(treeItem));
}
});
treeView.setCellFactory(p -> new AddMenuTreeCell());
tree.setExpanded(true);
root.setLeft(treeView);
tree.getChildren().add(item1);
Scene scene = new Scene(root, 700, 500);
primaryStage.setTitle("Tree View");
primaryStage.setScene(scene);
primaryStage.show();
}
private static class AddMenuTreeCell extends TextFieldTreeCell<String> {
private ContextMenu menu = new ContextMenu();
private TextField textField;
public AddMenuTreeCell() {
MenuItem newitem1 = new MenuItem("Insert Roots");
MenuItem newitem2 = new MenuItem("Insert Coordinates");
menu.getItems().addAll(newitem1, newitem2);
newitem1.setOnAction(arg0 -> {
TreeItem<String> item3 = new TreeItem<>("Root" + rootNr++);
getTreeItem().getChildren().add(item3);
});
newitem2.setOnAction(arg0 -> {
TreeItem<String> newLeaf = new TreeItem<>("Coordinates" + coordinateNr++);
TreeItem<String> uxItem1 = new TreeItem<>("X");
map.put(uxItem1, getrightPane1());
TreeItem<String> uyItem1 = new TreeItem<>("y");
map.put(uyItem1, getrightPane1());
newLeaf.getChildren().add(uxItem1);
newLeaf.getChildren().add(uyItem1);
getTreeItem().getChildren().add(newLeaf);
});
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (!isEditing()) {
setText(item);
setGraphic(getTreeItem().getGraphic());
if (!(getTreeItem().isLeaf() && getTreeItem().getParent() == null)) {
setContextMenu(menu);
}
}
}
}
}
private static BorderPane getrightPane1() {
TextField textf1 = new TextField();
TextField textf2 = new TextField();
BorderPane root1 = new BorderPane();
VBox vbox = new VBox(20);
vbox.setPadding(new Insets(10));
HBox h1 = new HBox(7);
HBox h2 = new HBox(7);
textf1.setPrefWidth(100);
textf1.setPromptText("Enter Height");
textf1.setOnKeyReleased(event -> {
if (textf1.getText().length() > 0 && textf2.getText().length() > 0) {
Rectangle rect1 = new Rectangle();
rect1.setHeight(Double.parseDouble(textf1.getText()));
rect1.setWidth(Double.parseDouble(textf2.getText()));
rect1.setFill(null);
rect1.setStroke(Color.BLUE);
root1.setCenter(rect1);
}
});
textf2.setPrefWidth(100);
textf2.setPromptText("Enter Width");
textf2.setOnKeyReleased(event -> {
if (textf1.getText().length() > 0 && textf2.getText().length() > 0) {
Rectangle rect2 = new Rectangle();
rect2.setHeight(Double.parseDouble(textf1.getText()));
rect2.setWidth(Double.parseDouble(textf2.getText()));
rect2.setFill(null);
rect2.setStroke(Color.RED);
root1.setCenter(rect2);
}
});
if (textf1.getText().length() > 0 && textf2.getText().length() > 0 && root1.getCenter() == null) {
Rectangle rect = new Rectangle();
rect.setHeight(Double.parseDouble(textf1.getText()));
rect.setWidth(Double.parseDouble(textf2.getText()));
rect.setFill(null);
rect.setStroke(Color.RED);
root1.setCenter(rect);
}
h1.getChildren().addAll(new Label("Y:"), textf1);
h2.getChildren().addAll(new Label("X:"), textf2);
vbox.getChildren().addAll(h1, h2);
root1.setLeft(vbox);
return root1;
}
private static BorderPane getRootsPanel(String root) {
BorderPane root2 = new BorderPane();
HBox hbox = new HBox(10);
hbox.setPadding(new Insets(40));
hbox.setAlignment(Pos.TOP_CENTER);
for (Map.Entry<TreeItem<String>, BorderPane> entry : map.entrySet()) {
if (entry.getKey().getParent().getParent().getValue().equals(root)) {
Rectangle rect1 = (Rectangle) entry.getValue().getCenter();
if (rect1 != null) {
Rectangle rect2 = new Rectangle();
rect2.setWidth(rect1.getWidth());
rect2.setHeight(rect1.getHeight());
rect2.setFill(rect1.getFill());
rect2.setStroke(rect1.getStroke());
Platform.runLater(() -> hbox.getChildren().addAll(rect2));
}
}
}
Platform.runLater(() -> root2.setLeft(hbox));
return root2;
}
}
With this code user can make tree shown in picture. 2 and 3 ( called root nodes) will show 4 rectangles due to each has 2 coordinate inside and 1st node should show total of 8 rectangles horizontally. but my first node show nothing. that is the problem.
[Note: i asked this question before but didn't get any response. Previously i edited this question many times and i don't have much reputation to put bounty (because i am new on stack-overflow)]
Please i need help on this problem.
Thank you
Upvotes: 0
Views: 453
Reputation: 2297
Mustafa, for your problem I have this variant of solution.
First of all instead of String as a main value type for tree items let work with specific value objects. Based on these objects you will be able to walk down in tree from any node and collect all rectangles recursively.
import javafx.scene.Node;
abstract class MyNode {
private final String label;
private Node rectangle;
MyNode(String label) {
this.label = label;
}
String getLabel() {
return label;
}
Node getRectangle() {
return rectangle;
}
void setRectangle(Node rectangle) {
this.rectangle = rectangle;
}
}
class MyRootNode extends MyNode {
MyRootNode(String label) {
super(label);
}
}
class MyCoordinateNode extends MyNode {
MyCoordinateNode(String label) {
super(label);
}
}
The main class was a bit reworked correspondingly
public class MyMain extends Application {
private static int rootNr = 0;
private static int coordinateNr = 0;
public static void main(String[] args) {
launch(args);
}
private static final Map<TreeItem<MyNode>, BorderPane> map = new HashMap<>();
@Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
TreeItem<MyNode> mainTree = new TreeItem<>(new MyRootNode("Main System"));
mainTree.setExpanded(true);
TreeView<MyNode> treeView = new TreeView<>(mainTree);
treeView.setCellFactory(p -> new AddMenuTreeCell());
treeView.setOnMouseClicked((event) -> {
final TreeItem<MyNode> treeItem = treeView.getSelectionModel().getSelectedItem();
if (treeItem.getValue() instanceof MyRootNode) {
root.setCenter(getRootsPanel(treeItem));
} else {
root.setCenter(map.get(treeItem));
}
});
root.setLeft(treeView);
Scene scene = new Scene(root, 700, 700);
primaryStage.setTitle("Tree View");
primaryStage.setScene(scene);
primaryStage.show();
}
private static class AddMenuTreeCell extends TextFieldTreeCell<MyNode> {
private ContextMenu menu = new ContextMenu();
AddMenuTreeCell() {
MenuItem newitem1 = new MenuItem("Insert Root");
MenuItem newitem2 = new MenuItem("Insert Coordinates");
menu.getItems().addAll(newitem1, newitem2);
newitem1.setOnAction(arg0 -> {
TreeItem<MyNode> item = new TreeItem<>(new MyRootNode("Root" + rootNr++));
getTreeItem().getChildren().add(item);
});
newitem2.setOnAction(arg0 -> {
TreeItem<MyNode> uxItem1 = new TreeItem<>(new MyCoordinateNode("X"));
map.put(uxItem1, getRightPane(uxItem1));
TreeItem<MyNode> uyItem1 = new TreeItem<>(new MyCoordinateNode("Y"));
map.put(uyItem1, getRightPane(uyItem1));
TreeItem<MyNode> newLeaf = new TreeItem<>(new MyRootNode("Coordinates" + coordinateNr++));
newLeaf.getChildren().add(uxItem1);
newLeaf.getChildren().add(uyItem1);
getTreeItem().getChildren().add(newLeaf);
});
}
@Override
public void updateItem(MyNode item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (!isEditing()) {
setText(item.getLabel());
setGraphic(getTreeItem().getGraphic());
if (item instanceof MyRootNode) {
setContextMenu(menu);
}
}
}
}
}
private static BorderPane getRightPane(final TreeItem<MyNode> curTreeItem) {
TextField textf1 = new TextField();
TextField textf2 = new TextField();
BorderPane root1 = new BorderPane();
VBox vbox = new VBox(20);
vbox.setPadding(new Insets(10));
HBox h1 = new HBox(7);
HBox h2 = new HBox(7);
textf1.setPrefWidth(100);
textf1.setPromptText("Enter Height");
textf1.setOnKeyReleased(event -> {
if (textf1.getText().length() > 0 && textf2.getText().length() > 0) {
Rectangle rect = getRectangle(textf1, textf2, Color.BLUE);
root1.setCenter(rect);
curTreeItem.getValue().setRectangle(rect);
}
});
textf2.setPrefWidth(100);
textf2.setPromptText("Enter Width");
textf2.setOnKeyReleased(event -> {
if (textf1.getText().length() > 0 && textf2.getText().length() > 0) {
Rectangle rect = getRectangle(textf1, textf2, Color.RED);
root1.setCenter(rect);
curTreeItem.getValue().setRectangle(rect);
}
});
h1.getChildren().addAll(new Label("Y:"), textf1);
h2.getChildren().addAll(new Label("X:"), textf2);
vbox.getChildren().addAll(h1, h2);
root1.setLeft(vbox);
return root1;
}
private static Rectangle getRectangle(TextField textf1, TextField textf2, final Color blue) {
Rectangle rect = new Rectangle();
rect.setHeight(Double.parseDouble(textf1.getText()));
rect.setWidth(Double.parseDouble(textf2.getText()));
rect.setFill(null);
rect.setStroke(blue);
return rect;
}
private static BorderPane getRootsPanel(final TreeItem<MyNode> treeItem) {
BorderPane root = new BorderPane();
HBox hbox = new HBox(10);
hbox.setPadding(new Insets(40));
hbox.setAlignment(Pos.TOP_CENTER);
final List<MyNode> coordinateNodes = getCoordinateNodes(treeItem);
for (final MyNode coordinateNode : coordinateNodes) {
if (coordinateNode.getRectangle() != null) {
Platform.runLater(() -> hbox.getChildren().addAll(coordinateNode.getRectangle()));
}
}
Platform.runLater(() -> root.setLeft(hbox));
return root;
}
private static List<MyNode> getCoordinateNodes(final TreeItem<MyNode> treeItem) {
final List<MyNode> result = new ArrayList<>();
if (treeItem.getValue() instanceof MyRootNode) {
for (final TreeItem<MyNode> child : treeItem.getChildren()) {
result.addAll(getCoordinateNodes(child));
}
} else {
result.add(treeItem.getValue());
}
return result;
}
}
This is an example where I created some roots and children and selected the top root to see all sub rectangles:
You are welcome to learn my version to understand what was changed. Note, this is draft variant and may be improved according to your needs. You are welcome with any questions.
Upvotes: 1
Reputation: 31
I have checked your code and I found out something.
In my opinion, When you select 1st node, treeItem.getChildren() method has only 2 children. It means 4,5,6 and 7 are not a child of 1st node. They are a child of 2 or 3.
So, when you select 1st node, below in your code doesn't work.
if (treeItem.getChildren().stream().anyMatch(child -> child.getValue().startsWith("C"))) {
root.setCenter(getRootsPanel(treeItem.getValue()));
}
Upvotes: 2