I have a JTree which is constructed with the following method:
(The BKMNode class extends DefaultMutableTreeNode, and theDataNode simply holds the data)
void populateTree(BKMNode parent) {
for (DataNode node : nodes) {
BKMNode treeNode = new BKMNode(node.name,node.fullName,null);
// check if this node was already added before
if (! existingNodes.contains(ip + "." + node.fullName)) {
existingNodes.add(ip + "." + node.fullName);
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
model.insertNodeInto(treeNode, parent, parent.getChildCount());
System.out.println("adding " + ip + "." + node.fullName);
}
node.populateTree(treeNode);
}
// some more non-relevant code...
When the tree is created at the application startup, everything is fine.
But once in a while my application adds nodes to the tree using the same method.
When the application attempts to add a new node to the tree in does print the text, but nothing changes on the GUI.
I tried calling JTree.invalidate(), validate(), repaint(), reload() but nothing seems to help.
The populateTree method is always called from the EDT.
Does anyone know what's the problems here?
Thanks a lot in advance!
Trust me, I tried using every invalidate, validate, repaint, reload method
Sorry, I don't trust you, people make silly mistakes all the time. That is why we need a SSCCE to see exactly what your are doing. Having said that, there is no reason to invoke any of those methods. invalidate(), validate() are used when you add/remove components from a Container, which you have not done. When you update a model, the model is responsible for notifying the view so the view can repaint itself.
but nothing changes on the GUI
What do you expect to change?
Inserting a node inserts a node into the model. If the parent node is expanded, then yes you should see the inserted node. However if the parent node is collapsed you will not see a change.
If you want to see the node after you insert it then you can use the tree.expandPath(...) method.
The basic code you posted works fine for me when I insert a default node containing a String value. Maybe the problem is your custom node? So the first thing you need to do is create a SSCCE that works with the default node. Once that works you replace the default node with your custom node. If it works, great. If not you know the problem is your custom node.
Based on the code provided it should work, so you need to give us more to work with.
Solved! I added some breakpoints at the "nodesWereInserted" method in the DefaultTreeModel's source and run the application with a debugger. It showed that the new nodes were added with a null parent! Further investigation showed the problem - the node.populateTree(treeNode); line added the new node without it being connected its indended parent.
This is the new (working) code. Thanks a lot for the help.
void populateTree(BKMNode parent) {
for (DataNode node : nodes) {
BKMNode treeNode = new BKMNode(node.name,node.fullName,null);
// check if this node was already added before
if (! existingNodes.contains(ip + "." + node.fullName)) {
existingNodes.add(ip + "." + node.fullName);
DefaultTreeModel model = (DefaultTreeModel)tree.getModel();
model.insertNodeInto(treeNode, parent, parent.getChildCount());
node.bkmNode = treeNode;
node.populateTree(treeNode);
} else {
node.populateTree(node.bkmNode);
}
} // for
Related
everyone. I'm new in working with aem. I'm using aem 6.4. My task is to programmatically sort the order of the contents of a cq:project in aem depending on the content of a JSON file.
The content of the JSON file should be set as the initial child instead of the children sorted by their creation date.
This is the current structure of my cq:page. If the child2 is the one indicated in the JSON file, it should be the first one to be displayed. The content of the JSON file is just the name of one child so even though there are 10 children, the content of the JSON file should always be the first one in the list.
I've spent hours researching on how I can implement this although I still can't find any solution. Any insights on how should I create this? Thanks!
As I understand it, you want a way to order a named child of a cq:Page to be first in the list.
This is possible because cq:Page is an orderable node. This would not be possible otherwise. you chan check any nodetype in CRX Explorer.
I think adding the bit about JSON complicates the question. You just need a simple method such as the following:
private void orderAsFirstChild(String childName, Node parentNode) throws RepositoryException {
if (parentNode.hasNode(childName)) {
// find current first child name
String firstChildName = Optional.ofNullable(parentNode.getNodes())
.map(NodeIterator::nextNode)
.map(node -> {
try {
node.getName();
} catch (RepositoryException e) {
e.printStackTrace();
}
return (String) null;
}) //
.orElse(null);
parentNode.orderBefore(childName, firstChildName);
}
}
You should probably clean this up a little, but this is the general idea using Node#orderBefore
This may helps -
Get the children from the parent node.(you will get 'iterator' convert it to list here-Convert Iterator to ArrayList)
Delete all child nodes now. And keep the back up of above list.
iterate through the list , identify the node which you want place first(by title or some other property) add that to a separate set(LinkedHashSet- to maintain order).
Now add the remaining items/nodes in the same order after your specific node in the above set.(you may need to iterate through again)
Now this Set has nodes/Resources in the order which you want, iterate , create nodes and save your changes.
I have implemented https://blogs.oracle.com/geertjan/file-browser to show only folders (changed == in accept() to !=). However, no matter what I have done it only calls the FileFilterNodeChildren for the first level, the children of the root node. So what I get is the folders of the root node (the directory I want) but it show ALL files and folders below this level. I have put in statements that verify that the filter function is only called for the first level.
What do I need to do to filter the children of the first level and below?
Inside of createNodes() you need to wrap the child nodes with instances of FileFilterNode. Here is a revised version of createNodes():
#Override
protected Node[] createNodes(Node object) {
List<Node> result = new ArrayList<Node>();
for (Node node : super.createNodes(object)) {
if (accept(node)) {
// This is the only changed line
result.add(new FileFilterNode(node));
}
}
return result.toArray(new Node[0]);
}
This was tested in NetBeans 8.2 on Windows and works as expected. The "File Browser" displays a tree containing only folders at all levels.
I have a sort of convoluted question. I'll try my best to explain. I am working on a Adobe CQ codebase that is JCR and Java-based.
I have a Java ArrayList declaration like this:
ArrayList<Map<String,Property>> list6 = new ArrayList<Map<String,Property>>();
Furthermore I have a linked list defined by CQ/Java code elsewhere in the code. That linked list is called linkSet6. Each 'node' in the list goes by the name links
I am trying to get the content from linkSet6 to ArrayList list6.
The problem I am facing is linkSet6 always exists but it may or may not have links in it. I am doing this and it works fine whenever there are "links"
if(currentNode != null && currentNode.hasNode("linkSet6")) {
baseNode = currentNode.getNode("linkSet6").getNode("links");
list6 = Utilities.parseStructuredMultifield(baseNode);
}
But when linkSet6 is emptyI get this error:
org.apache.sling.api.scripting.ScriptEvaluationException: An exception occurred processing JSP page /apps/citrixosd-responsive/components/content/footerNavigation/footerNavigation.jsp at line 41
Line 41 is this:
baseNode = currentNode.getNode("linkSet6").getNode("links");
I've tried size(),length() etc to check but to no avail. Any tip on how to check if links exist before doing getNode("links").
You can validate if the node exists by using Session.nodeExists(String) method.
if (session.nodeExists(currentNode.getPath + "/linkSet6")) {
...
}
The session object is usually acquired via the ResourceResolver object: resolver.adaptTo(Session.class)
Anyway - I recommend jumping into the Sling abstraction layer. Working with Resource and ResourceResolver is bit more convenient in such case (e.g. getResource will return you a null when a resource does not exist).
hasNode("links") will return true if the node links exists
I have a link, if i click the link i need to call another Js using new keyword like below.
<a style="padding: 2px 15px" data-dojo-attach-event="click:display">Form</a>
display : function(){
new com.cn.clb.dr.mytasks.BrandForm({
formInfo: brandForm,
brand: brandName
}, formPlacer).initialize();
}
Here very first time(1st time page loading) above js called perfectly, After that, i was clicked the link the above js is not called.
In the JS i have included both postcreate() and initialize().
Please tell me how to call the js.
Based on the additional information that Dijit is telling you you're trying to register a widget with an ID that's already registered, you need to destroy the first widget you create before creating another one based on the same element.
Additionally, the second argument passed to widget constructors indicates srcNodeRef, which is a node that will be replaced with the widget's own DOM. I'm sort of guessing here since there's not much context, but you probably don't want to be passing the same node reference to it multiple times since it will probably be invalid after the first.
Here is an example of something I would expect to work better, which destroys the widget if it exists from a previous call using destroyRecursive, and uses placeAt to place the widget under a parent node rather than using the srcNodeRef argument to replace a node.
display : function(){
var parentNode;
if (this._displayWidget) {
parentNode = this._displayWidget.domNode.parentNode;
this._displayWidget.destroyRecursive();
}
else {
parentNode = formPlacer.parentNode;
}
this._displayWidget = new com.cn.clb.dr.mytasks.BrandForm({
formInfo: brandForm,
brand: brandName
}).placeAt(parentNode).initialize();
}
Note that this currently doesn't take into account position among siblings in the parent node; it should be possible to amend the placeAt call accordingly.
Finally i got the fix, we are using ID attribute in html file, so instead of using ID am using data-dojo-attach-point in the html. After this change its working fine now.
instead of using id am using data-dojo-attach-point.
I am creating an editor application, and I am having a problem with my menus. In the object menu, I want to display several objects types using a JTree. These object types are dynamically registered by plugins and follow this style:
trigger.button
trigger.lever
out.door.fallgate
trigger.plate
out.door.door
...
This list of names is unsorted and I want to build a TreeNode structure for a JTree like this:
trigger
button
lever
plate
out
door
fallgate
door
Additionally, if the user selects a leaf node, I need to recreate the object name (e.g. trigger.button) from the TreePath. Could someone please advise how this can be done.
In psuedocode, this is what you need to do...
public TreeNode buildTree(){
String[] names = new String[]; // fill this with the names of your plugins
TreeNode tree;
// for each plugin name...
for (int i=0;i<names.length;i++){
String currentName = names[i];
String[] splitName = currentName.split(".");
// loop over the split name and see if the nodes exist in the tree. If not, create them
TreeNode parent = tree;
for (int n=0;n<splitName.length;n++){
if (parent.hasChild(splitName[n])){
// the parent node exists, so it doesn't need to be created. Store the node as 'parent' to use in the next loop run
parent = parent.getChild(splitName[n]);
}
else {
// the node doesn't exist, so create it. Then set it as 'parent' for use by the next loop run
TreeNode child = new TreeNode(splitName[n]);
parent.addChild(child);
parent = child;
}
}
return tree;
}
This is only psuedocode - you'll need to do the work of implementing the TreeNode methods properly, etc. Give it a try yourself - if you have any more problems, create a question and show us that you've attempted to do it yourself, then we will be more willing to help you solve the minor problems.
see Oracle JTree tutorial
part Dynamically Changing a Tree, check the code example
similair idea