I have an anchor pane with many text fields and other controls. I want to take values of all controls and their names and id.
For example: how can I clear all textfield values?
Straightforward solution would be just traversing all children of AnchorPane and looking for TextFields:
for (Node node : anchorPane.getChildren()) {
System.out.println("Id: " + node.getId());
if (node instanceof TextField) {
// clear
((TextField)node).setText("");
}
}
In case you need a recursive way test this,
public class NodeUtils {
public static <T extends Pane> Map<Node, Object> formValues(T parent) {
return formValues(parent, new HashMap<>());
}
private static <T extends Pane> Map<Node, Object> formValues(T parent, Map<Node, Object> map) {
for (Node node : parent.getChildren()) {
// Nodes - You can add more.
if (node instanceof TextField) {
map.put(node, ((TextField) node).getText());
}
if (node instanceof PasswordField) {
map.put(node, ((PasswordField) node).getText());
}
if (node instanceof TextArea) {
map.put(node, ((TextArea) node).getText());
}
if (node instanceof CheckBox) {
map.put(node, ((CheckBox) node).isSelected());
}
// Recursive.
if (node instanceof Pane) {
formValues((Pane) node, map);
}
}
return map;
}
}
Test source,
Map<Node, Object> formValues = NodeUtils.formValues(source);
Get only the nodes
public class NodeUtils {
public static ArrayList<Node> getAllNodes(Parent root) {
ArrayList<Node> nodes = new ArrayList<>();
addAllDescendents(root, nodes);
return nodes;
}
private static void addAllDescendents(Parent parent, ArrayList<Node> nodes) {
// Get children.
List<Node> children = Collections.EMPTY_LIST;
if (parent instanceof ButtonBar) {
children = ((ButtonBar) parent).getButtons();
} else if (parent instanceof TabPane) {
for (Tab tab : ((TabPane) parent).getTabs()) {
Node tabContent = tab.getContent();
if (tabContent instanceof Parent) {
addAllDescendents((Parent) tab.getContent(), nodes);
} else {
// You can log and get a type that is not supported.
}
}
} else {
children = parent.getChildrenUnmodifiable();
}
// Add nodes.
for (Node node : children) {
nodes.add(node);
if (node instanceof Parent) {
addAllDescendents((Parent) node, nodes);
}
}
}
}
Test source,
List<Node> nodes = NodeUtils.getAllNodes(aPaneOrAnotherParentObject);
Heres a Java 8 version:
anchorPane.getChildren()
.filtered(node -> node instanceof TextField)
.forEach(node -> ((TextField)node).setText(""));
Related
I can't write correctly function that deletes one node from tree. If this node has children, they should move one level higher. Children of deleted element will have parent of deleted elem,ancestors will they on they places, but one level higher. How can I do it right?
import java.util.ArrayList;
import java.util.List;
public class Node<T> {
private T value;
private final List<Node<T>> listOfChildren;
private Node<T> parent;
public Node(){
super();
listOfChildren = new ArrayList<>();
}
public Node(T value){
this();
setValue(value);
}
public T getValue() {
return value;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
public List<Node<T>> getListOfChildren() {
return listOfChildren;
}
public void setValue(T value) {
this.value = value;
}
public int getNumberOfChildren() {
return listOfChildren.size();
}
public void addChildren(Node<T> child) {
parent = this;
listOfChildren.add(child);
}
public void removeChildAt(int index) {
if (index > listOfChildren.size()-1){
throw new IndexOutOfBoundsException( "This index is too big");
}
else {
Node<T> element = this.listOfChildren.get(index);
if (element.listOfChildren.size() > 0) {
// function...
}
listOfChildren.remove(index);
}
}
}
I think that writing dfs or bfs to walk through the tree is not the best way to realize this function. What is the best way to realize this function?
Children of deleted element will keep their descendants, so no walk through required
public void removeChildAt(int index) throws IndexOutOfBoundsException {
if (listOfChildren != null) {
Node<T> element = this.listOfChildren.get(index);
if (element.listOfChildren.size() > 0) {
this.listOfChildren.addAll(element.listOfChildren);
//element.listOfChildren.forEach(child -> child.setParent(this)); but you have no backward reference to parent
}
listOfChildren.remove(index);
}
else {
System.out.println("No children from this node");
}
}
So I¨m building a small game in which I want a search tree with all the possible moves. I¨m having some difficulties implementing the search tree however. I have managed to build a function that can calculate the move but then I¨m not sure how to build the tree, it should be recursivly. Each node should have a list with all possible moves.
public class Tree {
private Node root;
private int level;
public Tree(int level, Board board) {
this.level = level;
root = new Node(board);
}
public void add(Board board) {
int newLevel = board.numberPlacedDiscs();
if(newLevel>level){
//Add this at a new level.
Node newNode =new Node(board);
newNode.setParent(root);
root = newNode;
}else{
//add at this level.
root.addChild(new Node(board));
}
}
}
public class Tree {
private Node root;
private int level;
public Tree(int level, Board board) {
this.level = level;
root = new Node(board);
}
public void add(Board board) {
int newLevel = board.numberPlacedDiscs();
if(newLevel>level){
//Add this at a new level.
Node newNode =new Node(board);
newNode.setParent(root);
root = newNode;
}else{
//add at this level.
root.addChild(new Node(board));
}
}
}
As you can see I don't know how to add new Nodes. How do I know when to go down a level in the tree and add more nodes? Everytime a new disc is added to the board it should go down one level.
Here is a generic tree in Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TreeTest {
public static void main(String[] args) {
Tree tree = new Tree("root");
tree.root.addChild(new Node("child 1"));
tree.root.addChild(new Node("child 2"));
tree.root.getChild("child 1").addChild("child 1-1");
tree.root.getChild("child 1").addChild("child 1-2");
/*
root
-- child 1
---- child 1-1
---- child 1-2
-- child 2
*/
}
private static class Tree {
private Node root;
Tree(String rootData) {
root = new Node();
root.data = rootData;
root.children = new ArrayList<>();
}
public List<Node> getPathToNode(Node node) {
Node currentNode = node;
List<Node> reversePath = new ArrayList<>();
reversePath.add(node);
while (!(this.root.equals(currentNode))) {
currentNode = currentNode.getParentNode();
reversePath.add(currentNode);
}
Collections.reverse(reversePath);
return reversePath;
}
}
static class Node {
String data;
Node parent;
List<Node> children;
Node() {
data = null;
children = null;
parent = null;
}
Node(String name) {
this.data = name;
this.children = new ArrayList<>();
}
void addChild(String name) {
this.addChild(new Node(name));
}
void addChild(Node child) {
this.children.add(child);
}
void removeChild(Node child) {
this.children.remove(child);
}
public void removeChild(String name) {
this.removeChild(this.getChild(name));
}
public Node getChild(int childIndex) {
return this.children.get(childIndex);
}
Node getChild(String childName) {
for (Node child : this.children) {
if (child.data.equals(childName)) {
return child;
}
}
return null;
}
Node getParentNode() {
return this.parent;
}
}
}
blog post about generic tree data structure in java
Hope it helps
You can use this method to insert a Node into your tree:
private void insertNode(Node root, Node oldNode, Node newNode) {
if(root == null) {
return;
}
if(root == oldNode) {
oldNode.addChild(newNode);
return;
}
for(Node child : root.getChildren()) {
insertNode(child, oldNode, newNode);
}
}
So this method takes three parameters:
root - this is the root node of your tree.
oldNode - the node where you want to insert your newNode.
newNode - this is the node you want to be added to the children of your oldNode.
Node that if you pass a Node that does not exist in your tree, it will not throw any error. But you can modify to do it if you want.
I am new in tree like structures.I have write this kind of a tree.
How to iterate over a tree ?
How to find all roots (i have a method for the main root but i want to find all roots which are inside the tree) in a tree ?
What is the correct way to use a tree structure in java - every time write your one class or using TreeMap ?
TreeNode
public class TreeNode<T> {
private T value;
private boolean hasParent;
private ArrayList<TreeNode<T>> children;
public TreeNode(T value) {
if (value == null) {
throw new IllegalArgumentException("Cannot insert null value!");
}
this.value = value;
this.children = new ArrayList<TreeNode<T>>();
}
public final T getValue() {
return this.value;
}
public final void setValue(T value) {
this.value = value;
}
public final int getChildrenCount() {
return this.children.size();
}
public final void addChild(TreeNode<T> child) {
if (child == null) {
throw new IllegalArgumentException("Cannot insert null value!");
}
if (child.hasParent) {
throw new IllegalArgumentException("The node already has a parent!");
}
child.hasParent = true;
this.children.add(child);
}
public final TreeNode<T> getChild(int index) {
return this.children.get(index);
}
Tree
public class Tree<T> {
TreeNode<T> root;
public Tree(T value) {
if (value == null) {
throw new IllegalArgumentException("Cannot insert null value!");
}
this.root = new TreeNode<T>(value);
}
public Tree(T value, Tree<T>... children) {
this(value);
for (Tree<T> child : children) {
this.root.addChild(child.root);
}
}
public final TreeNode<T> getRoot() {
return this.root;
}
Here i can use all inner roots and all nodes.
while (!stack.isEmpty()) {
TreeNode<Integer> currentNode = stack.pop();
for (int i = 0; i < currentNode.getChildrenCount(); i++) {
TreeNode<Integer> childNode = currentNode.getChild(i);
if (childNode == null) {
System.out.println("Not a root.");
} else {
System.out.println(childNode.getValue());
counter += childNode.getChildrenCount();
}
}
}
The following codes are aimed to export tree data structure into Map<String, String> so that can be easier to manipulate later. But the funny thing is toString() method works flawlessly but toMap() method got one missing parent A, child B. Anyone has any idea?
public static void main(String[] args) {
MutableTree<String> tree = new MappedTreeStructure<String>();
tree.add("A", "B");
tree.add("A", "C");
tree.add("C", "D");
tree.add("E", "F");
System.out.println(tree);
Map<String, String> myMap = tree.toMap();
if (myMap != null) {
for (Map.Entry<String, String> entry : myMap.entrySet()) {
System.out.println("parent: " + entry.getKey() + ", child: "
+ entry.getValue());
}
}
}
private final Map<N, N> nodeParent = new HashMap<N, N>();
private final LinkedHashSet<N> nodeList = new LinkedHashSet<N>();
#Override
public boolean add(N parent, N node) {
boolean added = nodeList.add(node);
nodeList.add(parent);
if (added) {
nodeParent.put(node, parent);
}
return added;
}
#Override
public boolean remove(N node, boolean cascade) {
if (!nodeList.contains(node)) {
return false;
}
if (cascade) {
for (N child : getChildren(node)) {
remove(child, true);
}
} else {
for (N child : getChildren(node)) {
nodeParent.remove(child);
}
}
nodeList.remove(node);
return true;
}
#Override
public List<N> getRoots() {
return getChildren(null);
}
#Override
public N getParent(N node) {
return nodeParent.get(node);
}
#Override
public List<N> getChildren(N node) {
List<N> children = new LinkedList<N>();
for (N n : nodeList) {
N parent = nodeParent.get(n);
if (node == null && parent == null) {
children.add(n);
} else if (node != null && parent != null && parent.equals(node)) {
children.add(n);
}
}
return children;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
dumpNodeStructure(builder, null, "- ");
return builder.toString();
}
#Override
public Map<String, String> toMap() {
Map<String, String> map = new HashMap<String, String>();
dumpNodeToMap(map, null);
return map;
}
private void dumpNodeToMap(Map<String, String> map, N node) {
if (node != null) {
map.put((String) getParent(node), node.toString());
}
for (N child : getChildren(node)) {
dumpNodeToMap(map, child);
}
}
private void dumpNodeStructure(StringBuilder builder, N node, String prefix) {
if (node != null) {
builder.append(prefix);
builder.append(node.toString());
builder.append('\n');
prefix = " " + prefix;
}
for (N child : getChildren(node)) {
dumpNodeStructure(builder, child, prefix);
}
}
The output are following on console:
- A
- B
- C
- D
- E
- F
parent: null, child: E
parent: A, child: C
parent: C, child: D
parent: E, child: F
For references, these are the two interface classes being used:
public interface MutableTree <N extends Serializable> extends Tree<N> {
public boolean add (N parent, N node);
public boolean remove (N node, boolean cascade);
Map<String, String> toMap();
}
and
public interface Tree <N extends Serializable> extends Serializable {
public List<N> getRoots ();
public N getParent (N node);
public List<N> getChildren (N node);
}
Your toMap method returns a a Map<String, String> whose key is the parent element name and whose value is a single child element. This means that when the key is "A" only one child element can be stored, and this is being set to the last child element which is found, in this case "C", overwriting the entry for "A" which was pointing to "B".
Instead your toMap method needs to return a Map<String, List<String>> which maps from each parent node, such as "A", to a List of child elements, such as "B" and "C". Obviously it's fine if the List contains only one child element, but it must be a list in case there is more than one child.
The usual pattern for creating a List of items rather than a single item looks like this:
String parentNode = getParent(node).toString();
List<String> childElements = null;
if(map.contains(parentNode) {
// List of child elements already exists, so get it from the Map.
childElements = map.get(parentNode);
} else {
// List of child elements does not yet exist, so create a new List
// and add it to the Map.
childElements = new ArrayList<>();
map.put(parentNode, childElements);
}
childElements.add(node.toString());
I'm trying to write an implementation of a BinaryTree whose object can be of any type that implements Comparable. However, I realize that won't completely work. For example, A String and a Double wouldn't be able to be inserted into the same tree, even though they both implement Comparable.
So, I would like to know if it's possible to write the code such that the BinaryTree can be instantiated with any value whose type implements Comparable, but any ensuing elements added to the tree must all share the same supertype as the root's value.
Here's the code I have so far:
public class BinaryTree {
private Node root;
public BinaryTree() {
this.root = null;
}
public Node lookup(Comparable<Object> value) {
return lookup(this.root, value);
}
private Node lookup(Node node, Comparable<Object> value) {
Node match = null;
if (match != node) {
if (value == node.value) {
match = node;
} else if (value.compareTo(node.value) < 0) {
return lookup(node.left, value);
} else {
return lookup(node.right, value);
}
}
return match;
}
public Node lookupNonRecursively(Comparable<Object> value) {
return lookupNonRecursively(this.root, value);
}
private Node lookupNonRecursively(Node node, Comparable<Object> value) {
Node match = null;
if (match != node) {
if (value == node.value) {
match = node;
} else {
Node root = node;
boolean found = false;
while (!found && root != null) {
if (root.value.compareTo(value) < 0) {
if (root.left == null) {
root.left = match = new Node(value);
found = true;
} else {
root = root.left;
}
} else {
if (root.right == null) {
root.right = match = new Node(value);
found = true;
} else {
root = root.right;
}
}
}
}
}
return match;
}
public Node insert(Comparable<Object> value) {
return insert(this.root, value);
}
private Node insert(Node node, Comparable<Object> value) {
if (node == null) {
node = new Node(value);
} else {
if (node.value.compareTo(value) <= 0) {
insert(node.left, value);
} else {
insert(node.right, value);
}
}
return node;
}
public Node insertNonRecursively(Comparable<Object> value) {
return insertNonRecursively(this.root, value);
}
private Node insertNonRecursively(Node node, Comparable<Object> value) {
if (node == null) {
node = new Node(value);
} else {
Node root = node;
boolean inserted = false;
while (!inserted) {
if (node.value.compareTo(root.value) < 0) {
if (root.left == null) {
root.left = node = new Node(value);
inserted = true;
} else {
root = root.left;
}
} else {
if (root.right == null) {
root.right = node = new Node(value);
inserted = true;
} else {
root = root.right;
}
}
}
}
return node;
}
public static class Node {
private Node left;
private Node right;
private Comparable<Object> value;
public Node(Comparable<Object> value) {
this.left = null;
this.right = null;
this.value = value;
}
}
}
And as a test, this will throw the error, The method insert(Comparable<Object>) in the type BinaryTree is not applicable for the arguments (Integer), if I try to run code like the following:
BinaryTree tree = new BinaryTree();
tree.insert(new Integer(1));
You can see I've implemented some different BinaryTree methods for this class, but the same rules would need to apply: any value passed into lookup() or insert() would also need to share the root's supertype. I have a feeling this is where some variant of <T extends Comparable<? super T>> is going to come into play, but my mind is just not figuring this one out.
Any ideas for how I might accomplish this?
As noted by #jp-jee, here's my solution (also with logic and other bugs fixed from untested first attempt), which works beautifully:
public class BinaryTree<T extends Comparable<T>> {
private Node<T> root;
public BinaryTree() {
this.root = null;
}
public Node<T> lookup(T value) {
return lookup(this.root, value);
}
private Node<T> lookup(Node<T> node, T value) {
Node<T> match = null;
if (match != node) {
if (value.equals(node.value)) {
match = node;
} else if (value.compareTo(node.value) < 0) {
return lookup(node.left, value);
} else {
return lookup(node.right, value);
}
}
return match;
}
public Node<T> lookupNonRecursively(T value) {
return lookupNonRecursively(this.root, value);
}
private Node<T> lookupNonRecursively(Node<T> node, T value) {
Node<T> match = null;
if (match != node && value != null) {
if (value.equals(node.value)) {
match = node;
} else {
Node<T> searchRoot = node;
boolean found = false;
while (!found && searchRoot != null) {
if (value.equals(searchRoot.value)) {
match = searchRoot;
found = true;
} else if (value.compareTo(searchRoot.value) < 0) {
searchRoot = searchRoot.left;
} else {
searchRoot = searchRoot.right;
}
}
}
}
return match;
}
public void insert(T value) {
this.root = insert(this.root, value);
}
private Node<T> insert(Node<T> node, T value) {
if (node == null) {
node = new Node<T>(value);
} else {
if (value.compareTo(node.value) <= 0) {
node.left = insert(node.left, value);
} else {
node.right = insert(node.right, value);
}
}
return node;
}
public void insertNonRecursively(T value) {
this.root = insertNonRecursively(this.root, value);
}
private Node<T> insertNonRecursively(Node<T> node, T value) {
if (node == null) {
node = new Node<T>(value);
} else {
Node<T> runner = node;
boolean inserted = false;
while (!inserted) {
if (value.compareTo(runner.value) < 0) {
if (runner.left == null) {
runner.left = new Node<T>(value);
inserted = true;
} else {
runner = runner.left;
}
} else {
if (runner.right == null) {
runner.right = new Node<T>(value);
inserted = true;
} else {
runner = runner.right;
}
}
}
}
return node;
}
public static class Node<T extends Comparable<T>> {
private Node<T> left;
private Node<T> right;
private T value;
public Node(T value) {
this.left = null;
this.right = null;
this.value = value;
}
public Node<T> getLeft() {
return left;
}
public Node<T> getRight() {
return right;
}
public T getValue() {
return value;
}
}
}
Make your Binary Tree generic like
public class BinaryTree<T extends Comparable<T>>{
...
}
Whenever creating a BinaryTree instance, specify the containied type:
new BinaryTree<MyClass>();
Where MyClass must implement Comparable<MyClass>, i.e. be comparable to Objects of the same class.
Your methods would read as (example):
public Node lookup(T value) { ... }
The same applies for your Node class. Make it generic the same way.