Showing tree nodes and leaves
Hi,
I have a tree control populated by XML data. In my tree I
would like to show only the nodes and not the leaves. Is this
possible?
Thanks,
Janie
co-workers said example picture is misleading.. we can make the order work if everything is a "folder" but not a mix of "folders" and "files" (if making a visual reference to the windows browser). i.e - a file is represented as an empty folder.
TK1
. Mat1
. Mat2
. mat3
> kit1
.. comp1
.. comp2
.. comp3
. mat4
> kit2
.. comp4
.. comp5
.. comp6
. mat5
displays at
TK1
> kit1
.. comp1
.. comp2
.. comp3
> kit2
.. comp4
.. comp5
.. comp6
. mat1
. mat2
. mat3
. mat4
. mat5
we can make it work if everything is a folder. This is our current workaround.
TK1
> mat1
> mat2
> mat3
v kit1 (when expanded)
.. comp1
.. comp2
.. comp3
> mat4
> kit2 (when not expanded)
> mat5
Similar Messages
-
Is there a way to "mix" the nodes and leaves of the tree so that even if they are at the same level (1,2,3...), they will display in a specified order (via sort sequence, alphabetical, etc.).
History:
We are using the Tree UI element to display/manage a material bom interface. We seem to be running into an issue with displaying the nodes/leaves of the tree.. regardless of the order that the context is built (which is currently the order of the exploded BOM from from CS_BOM_EXPL_MAT_V2), the bom is displayed with the nested boms at the top of each level and the single materials below them. For example. If TK1 contains Material1, Material2, Material3, Kit1(containing component1, comp2, comp3), Material4, Kit2(containing comp4, comp5, comp6), and Material5 (in this order), the tree will display with the A level node as TK1, the next node as Kit1 (with its subleaves of comp1,comp2,comp3), Kit2(with subleaves of comp4,comp5,comp6), THEN Material1, material2, material3, material4, material5. Our users are adamant about the items displaying in the correct order (which should be alphabetical based on the description for one report and by location for purposes of inventory for another). I've searched but not been able to locate a similar question. If I've missed it, please point me in the right direction. The users want the tree, not a "tree" table. This is our first attempt at the tree, so maybe we're missing something basic?
TK1
-Mat1
-Mat2
-Mat3
-Kit1
--Comp1
--Comp2
--Comp3
-Mat4
-Kit2
--Comp4
--comp5
--comp6
-Material5
displays as
TK1
-Kit1
--Comp1
--Comp2
--Comp3
-Kit2
--Comp4
--Comp5
--Comp6
-Mat1
-Mat2
-Mat3
-Mat4
-Mat5co-workers said example picture is misleading.. we can make the order work if everything is a "folder" but not a mix of "folders" and "files" (if making a visual reference to the windows browser). i.e - a file is represented as an empty folder.
TK1
. Mat1
. Mat2
. mat3
> kit1
.. comp1
.. comp2
.. comp3
. mat4
> kit2
.. comp4
.. comp5
.. comp6
. mat5
displays at
TK1
> kit1
.. comp1
.. comp2
.. comp3
> kit2
.. comp4
.. comp5
.. comp6
. mat1
. mat2
. mat3
. mat4
. mat5
we can make it work if everything is a folder. This is our current workaround.
TK1
> mat1
> mat2
> mat3
v kit1 (when expanded)
.. comp1
.. comp2
.. comp3
> mat4
> kit2 (when not expanded)
> mat5 -
Hi,
I'm near sighted and thus dependent on being able to choose larger fonts. For the code editor, this poses no problem. For the widgets in the views surrounding the editor (containing tree nodes) and dialogs (with the Preferences dialog being one example), the font is very small at high screen resolutions (I don't want to resort to a lower resolution since I would like the fonts to appear as detailed as possible).
Is there any way to override the menu, tree node, and dialog font via command line switches and/or property/config files during JDeveloper startup in a platform independent way?
If it can't be done platform independently, what are the necessary steps on Linux (probably for the GTK lib) and Windows?
Thanks in advance!
Kind regards,
HolgerI previously developed under full screen option and my PC resolution was 1600x1200. But when the application was ran on other screens it was displaying with some page contents being cut out. It was due to other machines running on lower resoultion. I will need now redesign the pages to run on user defined lower resolution of 1280x1024. How do I setup Jdeveloper design tab to show for 1280x1024.
Thanks
Edited by: user5108636 on Feb 14, 2011 5:23 PM -
Hi,
I need to place ampersands in tree node text property. To get the text
rendered right I need to provide the text as, for example, Bed '&+amp+;'
Breakfast.
This tree node is rendering well in the browser as "Bed & Breakfast".
But if an action is associated with the tree node and I run the app
the tree node is rendering to "Bed '&+amp+;' Breakfast".
"&+amp+;" means the well formed XHTML for ampersand, if I had written this as it should be it would render in this post as &.
Is there any workaround?
Thanks.
StephanThe Tree Node is now rendering right, but I run into another problem. After selection I need to display the Tree Node text in a static text component. which worked with this code:
public String node_action() {
String fullId = tree1.getCookieSelectedTreeNode();
String id = fullId.substring(fullId.lastIndexOf(":")+1);
TreeNode selectedNode = (TreeNode) this.getForm1().findComponentById(id);
String category = selectedNode.getParentTreeNode((TreeNode) selectedNode).getText();
if ( category.indexOf("&") != -1 ) {
getSessionBean1().getClassified().setCategory(category.replace("&", "&"));
else {
getSessionBean1().getClassified().setCategory(category);
String subCategory = selectedNode.getText();
if ( subCategory.indexOf("&") != -1 ) {
getSessionBean1().getClassified().setSubCategory(subCategory.replace("&", "&"));
else {
getSessionBean1().getClassified().setSubCategory(subCategory);
categoryTextfield.setText(getSessionBean1().getClassified().getSubCategory());
categoryTextfield.setVisible(true);
return null;
}(some & in the code section are original meant to be the XHTML for ampersand.)
but for the few Tree Nodes which are prerendered now, the call
String subCategory = selectedNode.getText(); returns null.
How can I get the text of for those prerendered Tree Node?
Thanks.
Stephan -
Create a tree node and show the report on the same page
Hi,
I have created a tree for our organization and each node represents a unit. The top one is office level and followed by division and brach.
I have created a reprot on the same page as the tree node.
What I want to do is:
I would like to click a specific node and the report shows only that node and bellow. So, If I click division A and division A has two branch. my report shows only those two braches that bellong to division A.
Can someone help me?
Thank youThe only way it could work is using iframes. Now OBIEE 11g would not allow iframes inside it's dashboard. It offers a dashboard object called "Embedded content" which is a restricted iframe kinda thing but unless you get this object's id from generated HTML you can change it's content dynamically. Besides, such an implementation may break with next patch. So here is an idea.
Create a HTML page with two iframes, left one will hold all the reports with links (you can always generate a list of reports through catalog manager, open it in excel and make HTML links from it) that open report urls (in the format of ./saw.dll?GO&Path=....) in right iframe (using javascript open.window method). Once that page is working, call this page from dashboard using an action link. This is slightly twisted approach but at least it would give you what you asked for.
About making the report list dynamic, I am afraid there are no easy answers. OBIEE provides web service that will allow the users to query catalog to get a list of reports. You can try some basic JSP to access the web service and generate the list dynamically. But that is not something I can provide here. -
Help with building a JTree using tree node and node renderers
Hi,
I am having a few problems with JTree's. basically I want to build JTree from a web spider. The webspide searches a website checking links and stores the current url that is being processed as a string in the variable msg. I wan to use this variable to build a JTree in a new class and then add it to my GUI. I have created a tree node class and a renderer node class, these classes are built fine. can someone point me in the direction for actually using these to build my tree in a seperate class and then displaying it in a GUI class?
*nodeRenderer.java
import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.net.*;
public class nodeRenderer extends DefaultTreeCellRenderer
implements TreeCellRenderer
public static Icon icon= null;
public nodeRenderer() {
icon = new ImageIcon(getClass().getResource("icon.gif"));
public Component getTreeCellRendererComponent(
JTree tree,
Object value,
boolean sel,
boolean expanded,
boolean leaf,
int row,
boolean hasFocus) {
super.getTreeCellRendererComponent(
tree, value, sel,
expanded, leaf, row,
hasFocus);
treeNode node = (treeNode)(((DefaultMutableTreeNode)value).getUserObject());
if(icon != null) // set a custom icon
setOpenIcon(icon);
setClosedIcon(icon);
setLeafIcon(icon);
return this;
*treeNode.java
*this is the class to represent a node
import javax.swing.*;
import javax.swing.tree.*;
import java.util.*;
import java.net.*;
* Class used to hold information about a web site that has
* been searched by the spider class
public class treeNode
*Url from the WebSpiderController Class
*that is currently being processed
public String msg;
treeNode(String urlText)
msg = urlText;
String getUrlText()
return msg;
//gui.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.net.*;
import java.io.*;
import java.util.*;
public class gui extends JFrame implements Runnable
*declare variable, boolean
*thread, a object and a center
*pane
protected URL urlInput;
protected Thread bgThread;
protected boolean run = false;
protected WebSpider webSpider;
public gui()
*create the gui here
setTitle("Testing Tool");
setSize(600,600);
//add Buttons to the tool bar
start.setText("Start");
start.setActionCommand("Start");
toolBar.add(start);
ButtonListener startListener = new ButtonListener();
start.addActionListener(startListener);
cancel.setText("Cancel");
cancel.setActionCommand("Cancel");
toolBar.add(cancel);
ButtonListener cancelListener = new ButtonListener();
cancel.addActionListener(cancelListener);
close.setText("Close");
close.setActionCommand("Close");
toolBar.add(close);
ButtonListener closeListener = new ButtonListener();
close.addActionListener(closeListener);
//creat a simple form
urlLabel.setText("Enter URL:");
urlLabel.setBounds(100,36,288,24);
formTab.add(urlLabel);
url.setBounds(170,36,288,24);
formTab.add(url);
current.setText("Currently Processing: ");
current.setBounds(100,80,288,24);
formTab.add(current);
//add scroll bars to the error messages screen and website structure
errorPane.setAutoscrolls(true);
errorPane.setHorizontalScrollBarPolicy(javax.swing.
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
errorPane.setVerticalScrollBarPolicy(javax.swing.
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
errorPane.setOpaque(true);
errorTab.add(errorPane);
errorPane.setBounds(0,0,580,490);
errorText.setEditable(false);
errorPane.getViewport().add(errorText);
errorText.setBounds(0,0,600,550);
treePane.setAutoscrolls(true);
treePane.setHorizontalScrollBarPolicy(javax.swing.
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
treePane.setVerticalScrollBarPolicy(javax.swing.
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
treePane.setOpaque(true);
treeTab.add(treePane);
treePane.setBounds(0,0,580,490);
treeText.setEditable(false);
treePane.getViewport().add(treeText);
treeText.setBounds(0,0,600,550);
//create the tabbed window
centerPane.setBorder(new javax.swing.border.EtchedBorder());
formTab.setLayout(null);
errorTab.setLayout(null);
treeTab.setLayout(null);
centerPane.addTab("Search Parameters", formTab);
centerPane.addTab("Error Messages", errorTab);
centerPane.addTab("Website Structure", treeTab);
//add the tool bar and tabbed pane
getContentPane().add(toolBar, java.awt.BorderLayout.NORTH);
getContentPane().add(centerPane, java.awt.BorderLayout.CENTER);
*create the tool bar pane, a center pane, add the buttons,
*labels, tabs, a text field for user input here
javax.swing.JPanel toolBar = new javax.swing.JPanel();
javax.swing.JButton start = new javax.swing.JButton();
javax.swing.JButton cancel = new javax.swing.JButton();
javax.swing.JButton close = new javax.swing.JButton();
javax.swing.JTabbedPane centerPane = new javax.swing.JTabbedPane();
javax.swing.JPanel formTab = new javax.swing.JPanel();
javax.swing.JLabel urlLabel = new javax.swing.JLabel();
javax.swing.JLabel current = new javax.swing.JLabel();
javax.swing.JTextField url = new javax.swing.JTextField();
javax.swing.JPanel errorTab = new javax.swing.JPanel();
javax.swing.JTextArea errorText = new javax.swing.JTextArea();
javax.swing.JScrollPane errorPane = new javax.swing.JScrollPane();
javax.swing.JPanel treeTab = new javax.swing.JPanel();
javax.swing.JTextArea treeText = new javax.swing.JTextArea();
javax.swing.JScrollPane treePane = new javax.swing.JScrollPane();
javax.swing.JTree searchTree = new javax.swing.JTree();
*show the gui
public static void main(String args[])
(new gui()).setVisible(true);
*listen for the button presses and set the
*boolean flag depending on which button is pressed
class ButtonListener implements ActionListener
public void actionPerformed(ActionEvent event)
Object object = event.getSource();
if (object == start)
run = true;
startActionPerformed(event);
if (object == cancel)
run = false;
startActionPerformed(event);
if (object == close)
System.exit(0);
*this method is called when the start or
*cancel button is pressed.
void startActionPerformed (ActionEvent event)
if (run == true && bgThread == null)
bgThread = new Thread(this);
bgThread.start();
if (run == false && bgThread != null)
webSpider.cancel();
*this mehtod will start the background thred.
*the background thread is required so that the
*GUI is still displayed
public void run()
try
webSpider = new WebSpider(this);
webSpider.clear();
urlInput = new URL(url.getText());
webSpider.addURL(urlInput);
webSpider.run();
bgThread=null;
catch (MalformedURLException e)
addressError addErr = new addressError();
addErr.addMsg = "URL ERROR - PLEASE CHECK";
SwingUtilities.invokeLater(addErr);
*this method is called by the web spider
*once a url is found. Validation of navigation
*happens here.
public boolean urlFound(URL urlInput,URL url)
CurrentlyProcessing pro = new CurrentlyProcessing();
pro.msg = url.toString();
SwingUtilities.invokeLater(pro);
if (!testLink(url))
navigationError navErr = new navigationError();
navErr.navMsg = "Broken Link "+url+" caused on "+urlInput+"\n";
return false;
if (!url.getHost().equalsIgnoreCase(urlInput.getHost()))
return false;
else
return true;
*this method is called internally to check
*that a link works
protected boolean testLink(URL url)
try
URLConnection connection = url.openConnection();
connection.connect();
return true;
catch (IOException e)
return false;
*this method is called when an error is
*found.
public void URLError(URL url)
*this method is called when an email
*address is found
public void emailFound(String email)
/*this method will update any errors found inc
*address errors and broken links
class addressError implements Runnable
public String addMsg;
public void run()
errorText.append(addMsg);
current.setText("Currently Processing: "+ addMsg);
class navigationError implements Runnable
public String navMsg;
public void run()
errorText.append(navMsg);
*this method will update the currently
*processing field on the GUI
class CurrentlyProcessing implements Runnable
public String msg;
public void run()
current.setText("Currently Processing: " + msg );
//webspider.java
import java.util.*;
import java.net.*;
import java.io.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.tree.*;
import javax.swing.*;
*this class implements the spider.
public class WebSpider extends HTMLEditorKit
*make a collection of the URL's
protected Collection urlErrors = new ArrayList(3);
protected Collection urlsWaiting = new ArrayList(3);
protected Collection urlsProcessed = new ArrayList(3);
//report URL's to this class
protected gui report;
*this flag will indicate whether the process
*is to be cancelled
protected boolean cancel = false;
*The constructor
*report the urls to the wui class
public WebSpider(gui report)
this.report = report;
*get the urls from the above declared
*collections
public Collection getUrlErrors()
return urlErrors;
public Collection getUrlsWaiting()
return urlsWaiting;
public Collection getUrlsProcessed()
return urlsProcessed;
* Clear all of the collections.
public void clear()
getUrlErrors().clear();
getUrlsWaiting().clear();
getUrlsProcessed().clear();
*Set a flag that will cause the begin
*method to return before it is done.
public void cancel()
cancel = true;
*add the entered url for porcessing
public void addURL(URL url)
if (getUrlsWaiting().contains(url))
return;
if (getUrlErrors().contains(url))
return;
if (getUrlsProcessed().contains(url))
return;
/*WRITE TO LOG FILE*/
log("Adding to workload: " + url );
getUrlsWaiting().add(url);
*process a url
public void processURL(URL url)
try
/*WRITE TO LOGFILE*/
log("Processing: " + url );
// get the URL's contents
URLConnection connection = url.openConnection();
if ((connection.getContentType()!=null) &&
!connection.getContentType().toLowerCase().startsWith("text/"))
getUrlsWaiting().remove(url);
getUrlsProcessed().add(url);
log("Not processing because content type is: " +
connection.getContentType() );
return;
// read the URL
InputStream is = connection.getInputStream();
Reader r = new InputStreamReader(is);
// parse the URL
HTMLEditorKit.Parser parse = new HTMLParse().getParser();
parse.parse(r,new Parser(url),true);
catch (IOException e)
getUrlsWaiting().remove(url);
getUrlErrors().add(url);
log("Error: " + url );
report.URLError(url);
return;
// mark URL as complete
getUrlsWaiting().remove(url);
getUrlsProcessed().add(url);
log("Complete: " + url );
*start the spider
public void run()
cancel = false;
while (!getUrlsWaiting().isEmpty() && !cancel)
Object list[] = getUrlsWaiting().toArray();
for (int i=0;(i<list.length)&&!cancel;i++)
processURL((URL)list);
* A HTML parser callback used by this class to detect links
protected class Parser extends HTMLEditorKit.ParserCallback
protected URL urlInput;
public Parser(URL urlInput)
this.urlInput = urlInput;
public void handleSimpleTag(HTML.Tag t,MutableAttributeSet a,int pos)
String href = (String)a.getAttribute(HTML.Attribute.HREF);
if((href==null) && (t==HTML.Tag.FRAME))
href = (String)a.getAttribute(HTML.Attribute.SRC);
if (href==null)
return;
int i = href.indexOf('#');
if (i!=-1)
href = href.substring(0,i);
if (href.toLowerCase().startsWith("mailto:"))
report.emailFound(href);
return;
handleLink(urlInput,href);
public void handleStartTag(HTML.Tag t,MutableAttributeSet a,int pos)
handleSimpleTag(t,a,pos); // handle the same way
protected void handleLink(URL urlInput,String str)
try
URL url = new URL(urlInput,str);
if (report.urlFound(urlInput,url))
addURL(url);
catch (MalformedURLException e)
log("Found malformed URL: " + str);
*log the information of the spider
public void log(String entry)
System.out.println( (new Date()) + ":" + entry );
I have a seperate class for parseing the HTML. Any help would be greatly appreciated
mrvHi Sorry to be a pain again,
I have re worked the gui class so it looks like this now:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.net.*;
import java.io.*;
import java.util.*;
public class gui extends JFrame implements Runnable
*declare variable, boolean
*thread, a object and a center
*pane
protected URL urlInput;
protected Thread bgThread;
protected boolean run = false;
protected WebSpider webSpider;
public String msgInfo;
public String brokenUrl;
public String goodUrl;
public String deadUrl;
protected DefaultMutableTreeNode rootNode;
protected DefaultTreeModel treeModel;
public gui()
*create the gui here
setTitle("Testing Tool");
setSize(600,600);
//add Buttons to the tool bar
start.setText("Start");
start.setActionCommand("Start");
toolBar.add(start);
ButtonListener startListener = new ButtonListener();
start.addActionListener(startListener);
cancel.setText("Cancel");
cancel.setActionCommand("Cancel");
toolBar.add(cancel);
ButtonListener cancelListener = new ButtonListener();
cancel.addActionListener(cancelListener);
close.setText("Close");
close.setActionCommand("Close");
toolBar.add(close);
ButtonListener closeListener = new ButtonListener();
close.addActionListener(closeListener);
//creat a simple form
urlLabel.setText("Enter URL:");
urlLabel.setBounds(100,36,288,24);
formTab.add(urlLabel);
url.setBounds(170,36,288,24);
formTab.add(url);
current.setText("Currently Processing: ");
current.setBounds(100,80,288,24);
formTab.add(current);
//add scroll bars to the error messages screen and website structure
errorPane.setAutoscrolls(true);
errorPane.setHorizontalScrollBarPolicy(javax.swing.
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
errorPane.setVerticalScrollBarPolicy(javax.swing.
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
errorPane.setOpaque(true);
errorTab.add(errorPane);
errorPane.setBounds(0,0,580,490);
errorText.setEditable(false);
errorPane.getViewport().add(errorText);
errorText.setBounds(0,0,600,550);
treePane.setAutoscrolls(true);
treePane.setHorizontalScrollBarPolicy(javax.swing.
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
treePane.setVerticalScrollBarPolicy(javax.swing.
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
treePane.setOpaque(true);
treeTab.add(treePane);
treePane.setBounds(0,0,580,490);
treeText.setEditable(false);
treePane.getViewport().add(treeText);
treeText.setBounds(0,0,600,550);
//JTree
// NEW CODE
rootNode = new DefaultMutableTreeNode("Root Node");
treeModel = new DefaultTreeModel(rootNode);
treeModel.addTreeModelListener(new MyTreeModelListener());
tree = new JTree(treeModel);
tree.setEditable(true);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
treeText.add(tree);
//create the tabbed window
centerPane.setBorder(new javax.swing.border.EtchedBorder());
formTab.setLayout(null);
errorTab.setLayout(null);
treeTab.setLayout(null);
centerPane.addTab("Search Parameters", formTab);
centerPane.addTab("Error Messages", errorTab);
centerPane.addTab("Website Structure", treeTab);
//add the tool bar and tabbed pane
getContentPane().add(toolBar, java.awt.BorderLayout.NORTH);
getContentPane().add(centerPane, java.awt.BorderLayout.CENTER);
*create the tool bar pane, a center pane, add the buttons,
*labels, tabs, a text field for user input here
javax.swing.JPanel toolBar = new javax.swing.JPanel();
javax.swing.JButton start = new javax.swing.JButton();
javax.swing.JButton cancel = new javax.swing.JButton();
javax.swing.JButton close = new javax.swing.JButton();
javax.swing.JTabbedPane centerPane = new javax.swing.JTabbedPane();
javax.swing.JPanel formTab = new javax.swing.JPanel();
javax.swing.JLabel urlLabel = new javax.swing.JLabel();
javax.swing.JLabel current = new javax.swing.JLabel();
javax.swing.JTextField url = new javax.swing.JTextField();
javax.swing.JPanel errorTab = new javax.swing.JPanel();
javax.swing.JTextArea errorText = new javax.swing.JTextArea();
javax.swing.JScrollPane errorPane = new javax.swing.JScrollPane();
javax.swing.JPanel treeTab = new javax.swing.JPanel();
javax.swing.JTextArea treeText = new javax.swing.JTextArea();
javax.swing.JScrollPane treePane = new javax.swing.JScrollPane();
javax.swing.JTree tree = new javax.swing.JTree();
*show the gui
public static void main(String args[])
(new gui()).setVisible(true);
*listen for the button presses and set the
*boolean flag depending on which button is pressed
class ButtonListener implements ActionListener
public void actionPerformed(ActionEvent event)
Object object = event.getSource();
if (object == start)
run = true;
startActionPerformed(event);
if (object == cancel)
run = false;
startActionPerformed(event);
if (object == close)
System.exit(0);
*this method is called when the start or
*cancel button is pressed.
void startActionPerformed (ActionEvent event)
if (run == true && bgThread == null)
bgThread = new Thread(this);
bgThread.start();
//new line of code
treeText.addObject(msgInfo);
if (run == false && bgThread != null)
webSpider.cancel();
*this mehtod will start the background thred.
*the background thread is required so that the
*GUI is still displayed
public void run()
try
webSpider = new WebSpider(this);
webSpider.clear();
urlInput = new URL(url.getText());
webSpider.addURL(urlInput);
webSpider.run();
bgThread = null;
catch (MalformedURLException e)
addressError addErr = new addressError();
addErr.addMsg = "URL ERROR - PLEASE CHECK";
SwingUtilities.invokeLater(addErr);
*this method is called by the web spider
*once a url is found. Validation of navigation
*happens here.
public boolean urlFound(URL urlInput,URL url)
CurrentlyProcessing pro = new CurrentlyProcessing();
pro.msg = url.toString();
SwingUtilities.invokeLater(pro);
if (!testLink(url))
navigationError navErr = new navigationError();
navErr.navMsg = "Broken Link "+url+" caused on "+urlInput+"\n";
brokenUrl = url.toString();
return false;
if (!url.getHost().equalsIgnoreCase(urlInput.getHost()))
return false;
else
return true;
*this method is returned if there is no link
*on a web page, e.g. there us a dead end
public void urlNotFound(URL urlInput)
deadEnd dEnd = new deadEnd();
dEnd.dEMsg = "No links on "+urlInput+"\n";
deadUrl = urlInput.toString();
*this method is called internally to check
*that a link works
protected boolean testLink(URL url)
try
URLConnection connection = url.openConnection();
connection.connect();
goodUrl = url.toString();
return true;
catch (IOException e)
return false;
*this method is called when an error is
*found.
public void urlError(URL url)
*this method is called when an email
*address is found
public void emailFound(String email)
/*this method will update any errors found inc
*address errors and broken links
class addressError implements Runnable
public String addMsg;
public void run()
current.setText("Currently Processing: "+ addMsg);
errorText.append(addMsg);
class navigationError implements Runnable
public String navMsg;
public void run()
errorText.append(navMsg);
class deadEnd implements Runnable
public String dEMsg;
public void run()
errorText.append(dEMsg);
*this method will update the currently
*processing field on the GUI
public class CurrentlyProcessing implements Runnable
public String msg;
//new line
public String msgInfo = msg;
public void run()
current.setText("Currently Processing: " + msg );
* NEW CODE
* NEED THIS CODE SOMEWHERE
* treeText.addObject(msgInfo);
public DefaultMutableTreeNode addObject(Object child)
DefaultMutableTreeNode parentNode = null;
TreePath parentPath = tree.getSelectionPath();
if (parentPath == null)
parentNode = rootNode;
else
parentNode = (DefaultMutableTreeNode)
(parentPath.getLastPathComponent());
return addObject(parentNode, child, true);
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
Object child)
return addObject(parent, child, false);
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
Object child,boolean shouldBeVisible)
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);
if (parent == null)
parent = rootNode;
treeModel.insertNodeInto(childNode, parent, parent.getChildCount());
if (shouldBeVisible)
tree.scrollPathToVisible(new TreePath(childNode.getPath()));
return childNode;
public class MyTreeModelListener implements TreeModelListener
public void treeNodesChanged (TreeModelEvent e)
DefaultMutableTreeNode node;
node = (DefaultMutableTreeNode)
(e.getTreePath().getLastPathComponent());
try
int index = e.getChildIndices()[0];
node = (DefaultMutableTreeNode)
(node.getChildAt(index));
catch (NullPointerException exc)
public void treeNodesInserted(TreeModelEvent e)
public void treeStructureChanged(TreeModelEvent e)
public void treeNodesRemoved(TreeModelEvent e)
I beleive that this line of code is required:
treeText.addObject(msgInfo);
I have placed it where the action events start the spider, but i keep getting this error:
cannot resolve symbol
symbol : method addObject (java.lang.String)
location: class javax.swing.JTextArea
treeText.addObject(msgInfo);
Also the jtree is not showing the window that I want it to and I am not too sure why. could you have a look to see why? i think it needs a fresh pair of eyes.
Many thanks
MrV -
Custom tree node and DefaultTreeModel
Hello,
I would like to know if it's possible to use the following custom tree node with the DefaultTreeModel:
class MyTreeNode extends DefaultMutableTreeNode{
private String _argument = null;
public MyTreeNode(){}
public MyTreeNode(Object node, String argument){
super(node);
_argument = argument;
}I have tried it and it's not working but I think in theory it should work. Please correct me if I'm wrong.
The problem is that the tree won't display or insert the custom node when the insertNodeAt(...) method of
the DefaultTreeModel is called. I also tried using a custom tree listener and calling the .reload() method directly.
Any help will be very appreciated.
Thanks in advanced.Are you sure it's not being inserted into the model,
and just not being displayed?
Are you calling nodesWereInserted() after your
insertion?Thanks for your reply.
I've modified my app. so that the following method will populate the tree for testing only:
public void populateTree()
MyTreeNode root = new MyTreeNode("Root Node", "test");
DefaultTreeModel treeModel = new DefaultTreeModel(root);
JTree tree = new JTree(treeModel);
tree.setEditable(true);
tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
JScrollPane scrollPane = new JScrollPane(tree);
setLayout(new GridLayout(1,0));
add(scrollPane);
int childIdx[] = {0,1};
String p1Name = new String("Parent 1");
String p2Name = new String("Parent 2");
String c1Name = new String("Child 1");
String c2Name = new String("Child 2");
MyTreeNode p1 = new MyTreeNode(p1Name, "test");
MyTreeNode p2 = new MyTreeNode(p2Name, "test");
MyTreeNode c1 = new MyTreeNode(c1Name, "test");
MyTreeNode c2 = new MyTreeNode(c2Name, "test");
treeModel.insertNodeInto(p1, root, 0);
treeModel.insertNodeInto(p2, root, 1);
treeModel.nodesWereInserted(root, childIdx);
treeModel.insertNodeInto(c1, p1, 0);
treeModel.insertNodeInto(c2, p1, 1);
treeModel.nodesWereInserted(p1, childIdx);
treeModel.reload();
}And the result is that the "Root Node" will be displayed with "Parent1" and "Parent2" but "Parent1" won't have any children. Furthermore, if I try to remove "Parent1" using:
treeModel.removeNodeFromParent(p1);I will get an exception saying that node p1 has no parent, which suggests that the parent/child relation
is not being assigned by the model, even though the nodes (p1, p2) are displayed in the tree showing "Root node" as the parent. This is very strange.
Please help. -
Invalid B-tree node and disk stuck
Last night my 2 year old iMac froze up. When I re-started I received the flashing question-mark folder. I ended up inserting my OS X install disk and attempting to run the Disk Utility. I tried to repair the disk, but got the "Invalid B-tree node size" error with "The volume needs to be repaired."
I have tried a lot of things and will probably end up buying Disk Warrior and hoping that fixes it. BUT, I have another problem. I can't eject the OS X install disk. The option to eject is greyed out on the Disk Utility, the eject key doesn't work, and I can't find any way to unload the disk. Help would be appreciated.If you have an external hard drive it would be easier to clone your system to the external then boot to the external and run Disk Warrior from there. However if your system won't boot in the first place that won't work. You could pick up a copy of Disk Warrior from the Apple store.
http://www.bombich.com/software/ccc.html
George -
Skin Text of ADF Tree Node and Leaf separately
Hi,
Is it possible to skin a tree (ADF 11g), so that the text of a node is white on black, and text of a leaf is black on white?
I know I can change the icons for a node and a leaf separately , but can't find how to change the styles of the text seperately.
Groeten,
HJHHi,
1. Thanks.. i did understand...I am creating a tree with region-countries-location... so when i drag and drop the region view as a tree ... I get a default code like this
<af:tree value="#{bindings.RegionsView1.treeModel}" var="node"
selectionListener="#{bindings.RegionsView1.treeModel.makeCurrent}"
rowSelection="single" id="t1">
<f:facet name="nodeStamp">
<af:outputText value="#{node}" id="ot1" />
</f:facet>
</af:tree>
In this i have used output text ... so how do i use the styleclass.... I am a new bie so can u also tel me how to use implement the same and alsohow to create a styleclass..........
2. I have to display a seperate icons for parent node and leaf nodes.. can u tel me how to achieve this also...
Can u provide me ur sample and also docs so that it would be helpful...
Id: [email protected]
Thx.. waiting for your reply -
Swapped out the monitor on my Mac mini tonight and it wouldn't start back up. Managed to boot off the install disk and run disk utility, which gave the invalid b tree node error. Wasn't able to repair the disk, suggested a reformat. Is this worth my time? Or is the disk toasted? I got it in 2010, it's out of warranty and has already had the hard drive replaced once. Thanks!
-lauraIf you want to save the data from the drive, Phoenix might be able to copy (clone) it off on another volume. You can check it out at:
http://scsc-online.com/Phoenix.html
Phoenix does a file copying cloning, not block copy cloning, so a new index is generated on the drive when the copy is being made. If none of the files got lost, meaning just the index is screwed up, I would think this would work.
Regarding the hard drive an index problem isn't a hard drive problem. That hard drive may be in perfect working order, especially since it's fairly new. -
Dynamic add tree node and thread
Hi,
I implemented a thread by using SwingWorker class to execute the time-consuming file loading and processing task instead of the event-dispatching thread. However, I need to dynamically add node to a tree by using data returned by the file loader in my project's main frame like following:
if (source == loadAffyItem) {
//load affy file data to the application
loader = new AffyFileLoader();
//dynamically add node to the tree after data loading
rawDataNode = treePanel.addObject(null, "Raw Data");
DefaultMutableTreeNode node = new DefaultMutableTreeNode(new UserData("Pixel", loader.getPixelMatrix()));
pixelNode = treePanel.addObject(rawDataNode, node);
node = new DefaultMutableTreeNode(new UserData("Signal", loader.getSignalMatrix()));
signalNode = treePanel.addObject(rawDataNode, node);
}However, I always get a NullPointer error by doing this way since the code to dynamically add node to the tree using data returned from loader, but the loader is executed
in another thread and not finished yet. How could I make that code executed after the loader class is finished? Hope you could enlight me about this issue?
thanks in advance!
JennyYou'll have to redesign a bit. You could either have the separate thread add the node when it's finished (using SwingUtilities invokeLater to ensure you're updating the GUI in the Event Dispatch thread), or you could have the separate thread call-back or send an event when it's finished (and your main thread would listen).
-
Display Checkbox along Tree node and its child elements
Experts,
I want to display a checkbox in front of the Tree displayed in the view. This is used for me to select the child item value for my selection condition.
let say if the user selects the node, all the child elements will be used for search condition.
Otherwise, if the node is expanded, then the checkbox selected in the child element will be used for search condition...
Can u ppl suggest me how to design it, if possible can u share some sample code or procedure to customize the Tree as per the requirement...
thanx in advance,
James...hi
please go through this
<a href="http://integration of a tree structure in a web dynpro table">https://www.sdn.sap.comhttp://www.sdn.sap.comhttp://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.km.cm.docs/library/uuid/de59f7c2-0401-0010-f08d-8659cef543ce</a>
Thanks
Smitha -
JSF tree view GUI component and tree node actions
Hi,
I am new in using JSF and have a problem with my simple test application.
The application contains a tree view control with one static tree node and a separate text area. Clicking on the tree node shall fill the text area with the string 'hello'. Seems to be very simple, but it doesn't work.
What did I do?
First of all I use the Sun Java Studio Creator 2.
By double clicking on the tree node in the design window of the IDE a method called treeNode1_action() was created. I also added the String text to the session bean. treeNode1_Action() does not more than setting text='hello' ( getSessionBean().setText('hello'); ).
The jsp file contains the line
<ui:textArea binding="#{Page1.textArea}" id="textArea" style="height: 192px; left: 360px; top: 48px; position: absolute; width: 456px" text="#{SessionBean1.text}"/>, so the text of the text area is bound to the session property 'text'.
Running the application and clicking on the tree node does nothing except reloading the page (no 'hello' inside the text area).
Using the debugger showed me that the bean property text is set correctly to 'hello', also after reloading the page.
What did I do wrong?
What do I have to do to display 'hello' in the text area?
I would be glad for some good advice to solve my problem and looking forward for an answer.
Regards from germany
Matthiaswant to remove the green patch from the jsf tree componentas u said ,, it is COMPONENET so this is a pre-made creator component that u cant chnage its attributes ,,
instead u can extract Theam.jar file and change the icons ,, u i didnt do it before ,, but u may be find what u want there,
hope this will help
good luck
Mohammed -
Tree and Tree Node Components - Threadinar7
Hi All,
This is the seventh in the "Threadinar" series , please see Threadinar6 at
http://forum.sun.com/jive/thread.jspa?threadID=100601 for details
In this Threadinar we will focus on the
"Tree" and "Tree Node" Components
Let us begin our discussion with the Tree Component.
Tree Component
You can drag the Tree component from the Palette's Basic category to the Visual Designer to create a hierarchical tree structure with nodes that can be expanded and collapsed, like the nodes in the Outline window. When the user clicks a node, the row will be highlighted. A tree is often used as a navigation mechanism.
A tree contains Tree Node components, which act like hyperlinks. You can use a Tree Node to navigate to another page by setting its url property. You can also use a Tree Node to submit the current page. If the the Tree Node's action property is bound to an action event handler, selecting the node automatically submits the page. If the Tree Node's actionListener property is bound to an action listener, opening or closing the node automatically submits the page. You set Tree Node properties in the Tree Node Component Properties window.
* If you use this component to navigate between pages of a portlet, do not use the url property to link to a page. Instead, use the Navigation editor to set up your links to pages.
* Events related to tree node selection do not work correctly in portlets because the component uses cookies to pass the selected node id back and forth, and cookies are not correctly handled by the portlet container. You cannot handle tree node selection events in portlet projects.
Initially when you drop a tree on a page, it has one root node labeled Tree and one subnode labeled Tree Node 1. You can add more nodes by dragging them to the tree and dropping them either on the root node to create top level nodes or on existing nodes to create subnodes of those nodes. You can also right-click the Tree or any Tree Node and choose Add Tree Node to add a subnode to the node.
Additionally, you can work with the component in the Outline window, where the component and its child components are available as nodes. You can move a node from level to level easily in the Outline window, so you might want to work there if you are rearranging nodes. You can also add and delete tree nodes in the Outline window, just as in the Visual Designer.
The Tree component has properties that, among other things, enable you change the root node's displayed text, change the appearance of the text, specify if expanding or collapsing a node requires a trip to the server, and specify whether node selection should automatically open or close the tree. To set the Tree's properties, select the Tree component in your page and use the Tree Component Properties window.
The following Tutorial ("Using Tree Component") is very useful to learn using Tree components
http://developers.sun.com/prodtech/javatools/jscreator/learning/tutorials/2/sitemaptree.html
See Also the Technical Article - "Working with the Tree Component and Tree Node Actions"
http://developers.sun.com/prodtech/javatools/jscreator/reference/techart/2/tree_component.html
Tree Node Component
You can drag the Tree Node component from the Palette's Basic category to a Tree component or another tree node in the Visual Designer to create a node in a hierarchical tree structure, similar to the tree you see in the Outline window.
The tree node is created as a subnode of the node on which you drop it. If you drop the node on the tree component itself, a new node is created as a child of the root node. You can see the hierarchical structure clearly in the Outline window, where you can also easily move nodes around and reparent them.
You can also add a tree node either to a Tree component or to a Tree Node component by right-clicking the component and choosing Add Tree Node.
A Tree Node component by default is a container for an image and can be used to navigate to another page, submit the current page, or simply open or close the node if the node has child nodes.
* If you select the Tree Node component's node Tree Node icon in the Outline window, you can edit its properties in the Tree Node Properties window. You can set things like whether or not the Tree Node is expanded by default, the tooltip for the Tree Node, the label for the tree node, and the Tree Node's identifier in your web application.
* You can use a Tree Node to navigate to another page by setting its url property. You can also use a Tree Node to submit the current page. If the the Tree Node's action property is bound to an action event handler, selecting the node automatically submits the page. If the Tree Node's actionListener property is bound to an action listener, opening or closing the node automatically submits the page.
- Note: If you use this component to navigate between pages of a portlet, do not use the url property to link to a page. Instead, use the Navigation editor to set up your links to pages. In addition, events related to tree node selection do not work correctly in portlets because the component uses cookies to pass the selected node id back and forth, and cookies are not correctly handled by the portlet container. You cannot handle tree node selection events in portlet projects.
* If you select the image in the Tree Node, you can see that its icon property is set to TREE_DOCUMENT. If you right-click the image on the page and choose Set Image, you can either change the icon to another one or choose your own image in the Image Customizer dialog box. For more information on working with an image in a tree node, see Image component.
- Note: The image used in a tree node works best if it is 16x16 or smaller. Larger images can work, but might appear overlapped in the Visual Designer. You can right-click the component and choose Preview in Browser feature to check the appearance of the images.
Please share your comments, experiences, additional information, questions, feedback, etc. on these components.
------------------------------------------------------------------------------- --------------------One challenge I had experience was to make the tree
always expanded on all pages (I placed my tree menu
in a page fragment so I can just import it in my
pages).Did you solve this problem. It would be interesting to know what you did.
To expand a node you call setExpanded on the node. Here is some code from a tutorial that a coworker of mine is working on.
In the prerender method:
Integer expandedPersonId = getRequestBean1().getPersonId();
// If expandedPersonId is null, then we are not coming back
// from the Trip page. In that case we do not want any trip
// nodes to be pre-selected (highlighted) due to browser cookies.
if (expandedPersonId==null) {
try {
HttpServletRequest req =(HttpServletRequest)
getExternalContext().getRequest();
Cookie[] cookies = req.getCookies();
//Check if cookies are set
if (cookies != null) {
for (int loop =0; loop < cookies.length; loop++) {
if (cookies[loop].getName().equals
("form1:displayTree-hi")) {
cookies[loop].setMaxAge(0);
HttpServletResponse response =(HttpServletResponse)
getExternalContext().getResponse();
response.addCookie(cookies[loop]);
} catch (Exception e) {
error("Failure trying to clear highlighting of selected node:" +
e.getMessage());
} ... (in a loop for tree nodes)...
personNode.setExpanded(newPersonId.equals
(expandedPersonId));In the action method for the nodes:
// Get the client id of the currently selected tree node
String clientId = displayTree.getCookieSelectedTreeNode();
// Extract component id from the client id
String nodeId = clientId.substring(clientId.lastIndexOf(":")+1);
// Find the tree node component with the given id
TreeNode selectedNode =
(TreeNode) this.getForm1().findComponentById(nodeId);
try {
// Node's id property is composed of "trip" plus the trip id
// Extract the trip id and save it for the next page
Integer tripId = Integer.valueOf(selectedNode.getId().substring(4));
getRequestBean1().setTripId(tripId);
} catch (Exception e) {
error("Can't convert node id to Integer: " +
selectedNode.getId().substring(4));
return null;
It would also be great if I can set the tree
readonly where the user cannot toggle the expand
property of the tree (hope this can be added to the
tree functionality). -
Useful Code of the Day: Hideable Tree Nodes
Someone posted about how they could selectively hide tree nodes, and I already had this AbstractTreeModel class (which does some things DefaultTreeModel does and some it doesn't) and a concrete subclass for TreeNode objects, so I was thinking how one could do hideable nodes. So I came up with this solution.
There's 4 classes here:
- AbstractTreeModel is the base for the concrete TreeNodeTreeModel
- TreeNodeTreeModel extends AbstractTreeModel to support TreeNodes (DefautlMutableTreeNode, etc.)
- HideableMutableTreeNode which is a DefautlMutableTreeNode subclass which has a visible field (with is/set methods, of course).
- HideableTreeModel is the hideable model which is a subclass of TreeNodeTreeModel.
A HideableMutableTreeNode can be set invisible directly, but the tree still needs to be notified to update. So it's best to use the methods in HideableTreeModel which set a node's visibility which notify the tree of changes accordingly. Methods are also provided to check a full path's visibility or ensure a node including all parent nodes are visible.
A HideableTreeModel can take any TreeNode class, it doesn't have to be all HideableMutableTreeNodes, but only HideableMutableTreeNodes can be made invisible, of course. Any other TreeNode type would just be considered visible.
Hiding nodes works basically by making the tree think there's less nodes then there are. And to do this, the node counts and child index search just works by looping thru the parent's children. This has potential perfomance drawbacks of course, since one has to loop thru the node's children to get nodes every time. This could be alleviated by not supporting non-hideable nodes changing the internal maintenance of HideableMutableTreeNode contents. But I'll leave that to whoever really needs it. It shouldn't be a problem if there are are a relatively small set of child nodes in any given parent.
Also, note that the root node in the model cannot be made invisible, cuz it'd be redundant since JTree can be set to hide the root node.
// *** HideableTreeModel ***
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
* <code>HideableTreeModel</code> is an <code>TreeNodeTreeModel</code>
* implementation for <code>HideableMutableTreeNode</code> objects. The
* model can also take any other <code>javax.swing.tree.TreeNode</code>
* objects.
public class HideableTreeModel extends TreeNodeTreeModel {
* Creates a new <code>HideableTreeModel</code> object.
* @param root the root node
public HideableTreeModel(TreeNode root) {
super(root);
* Checks if the specified node is visible. A node can only be
* hidden if the node is an instance of <code>HideableMutableTreeNode</code>. <br />
* <br />
* Note that this only test the visibility of the specified node, not
* whether a parent node is visible. Use <code>isPathToNodeVisible(Object)</code>
* to check if the full path is visible.
* @param node the node
* @param true if the node is visible, else false
public boolean isNodeVisible(Object node) {
if(node != getRoot()) {
if(node instanceof HideableMutableTreeNode) {
return ((HideableMutableTreeNode)node).isVisible();
return true;
* Sets the specified node to be hidden. A node can only be made hidden
* if the node is an instance of <code>HideableMutableTreeNode</code>. <br />
* <br />
* Note that this method will notify the tree to reflect any changes to
* node visibility. <br />
* <br />
* Note that this will not alter the visibility of any nodes in the
* specified node's path to the root node. Use
* <code>ensurePathToNodeVisible(Object)</code> instead to make sure the
* full path down to that node is visible. <br />
* <br />
* Note that this method will notify the tree to reflect any changes to
* node visibility.
* @param node the node
* @param v true for visible, false for hidden
* @param true if the node's visibility could actually change, else false
public boolean setNodeVisible(Object node, boolean v) {
// can't hide root
if(node != getRoot()) {
if(node instanceof HideableMutableTreeNode) {
HideableMutableTreeNode n = (HideableMutableTreeNode)node;
// don't fix what ain't broke...
if(v != n.isVisible()) {
TreeNode parent = n.getParent();
if(v) {
// need to get index after showing...
n.setVisible(v);
int index = getIndexOfChild(parent, n);
super.nodeInserted(parent, n, index);
} else {
// need to get index before hiding...
int index = getIndexOfChild(parent, n);
n.setVisible(v);
super.nodeRemoved(parent, n, index);
return true;
return false;
* Checks if the specified node is visible and all nodes above it are
* visible.
* @param node the node
* @param true if the path is visible, else false
public boolean isPathToNodeVisible(Object node) {
Object[] path = getPathToRoot(node);
for(int i = 0; i < path.length; i++) {
if(!isNodeVisible(path)) {
return false;
return true;
* Sets the specified node and all nodes above it to be visible.
* Note that this method will notify the tree to reflect any changes to
* node visibility.
* @param node the node
public void ensurePathToNodeVisible(Object node) {
Object[] path = getPathToRoot(node);
for(int i = 0; i < path.length; i++) {
setNodeVisible(path[i], true);
* Returns the child of parent at index index in the parent's child array.
* @param parent the parent node
* @param index the index
* @return the child or null if no children
public Object getChild(Object parent, int index) {
if(parent instanceof TreeNode) {
TreeNode p = (TreeNode)parent;
for(int i = 0, j = -1; i < p.getChildCount(); i++) {
TreeNode pc = (TreeNode)p.getChildAt(i);
if(isNodeVisible(pc)) {
j++;
if(j == index) {
return pc;
return null;
* Returns the number of children of parent.
* @param parent the parent node
* @return the child count
public int getChildCount(Object parent) {
int count = 0;
if(parent instanceof TreeNode) {
TreeNode p = (TreeNode)parent;
for(int i = 0; i < p.getChildCount(); i++) {
TreeNode pc = (TreeNode)p.getChildAt(i);
if(isNodeVisible(pc)) {
count++;
return count;
* Returns the index of child in parent.
* @param parent the parent node
* @param child the child node
* @return the index of the child node in the parent
public int getIndexOfChild(Object parent, Object child) {
int index = -1;
if(parent instanceof TreeNode && child instanceof TreeNode) {
TreeNode p = (TreeNode)parent;
TreeNode c = (TreeNode)child;
if(isNodeVisible(c)) {
index = 0;
for(int i = 0; i < p.getChildCount(); i++) {
TreeNode pc = (TreeNode)p.getChildAt(i);
if(pc.equals(c)) {
return index;
if(isNodeVisible(pc)) {
index++;
return index;
* Main method for testing.
* @param args the command-line arguments
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
HideableMutableTreeNode root = new HideableMutableTreeNode("root");
root.add(new HideableMutableTreeNode("child_1"));
final HideableMutableTreeNode c2 = new HideableMutableTreeNode("child_2");
c2.setVisible(false);
final HideableMutableTreeNode c2a = new HideableMutableTreeNode("child_2_A");
c2.add(c2a);
c2.add(new HideableMutableTreeNode("child_2_B"));
root.add(c2);
HideableMutableTreeNode c3 = new HideableMutableTreeNode("child_3");
HideableMutableTreeNode cC = new HideableMutableTreeNode("child_3_C");
cC.setVisible(false);
c3.add(cC);
c3.add(new HideableMutableTreeNode("child_3_D"));
root.add(c3);
root.add(new HideableMutableTreeNode("child_4"));
root.add(new HideableMutableTreeNode("child_5"));
DefaultMutableTreeNode c6 = new DefaultMutableTreeNode("child_6");
c6.add(new DefaultMutableTreeNode("child_6_A"));
c6.add(new DefaultMutableTreeNode("child_6_B"));
root.add(c6);
final HideableTreeModel model = new HideableTreeModel(root);
JTree tree = new JTree(model);
f.getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER);
JButton b = new JButton("toggle");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
model.setNodeVisible(c2, !model.isNodeVisible(c2));
//model.ensurePathToNodeVisible(c2a);
f.getContentPane().add(b, BorderLayout.SOUTH);
f.pack();
f.setSize(300, 500);
f.show();
// *** HideableMutableTreeNode ***
import javax.swing.*;
import javax.swing.tree.*;
* <code>HideableMutableTreeNode</code> is a <code>DefaultMutableTreeNode</code>
* implementation that works with <code>HideableTreeModel</code>.
public class HideableMutableTreeNode extends DefaultMutableTreeNode {
* The node is visible flag.
public boolean visible = true;
* Creates a tree node that has no parent and no children, but which
* allows children.
public HideableMutableTreeNode() {
super();
* Creates a tree node with no parent, no children, but which allows
* children, and initializes it with the specified user object.
* @param userObject - an Object provided by the user that
* constitutes the node's data
public HideableMutableTreeNode(Object userObject) {
super(userObject);
* Creates a tree node with no parent, no children, initialized with the
* specified user object, and that allows children only if specified.
* @param userObject - an Object provided by the user that
* constitutes the node's data
* @param allowsChildren - if true, the node is allowed to have child
* nodes -- otherwise, it is always a leaf node
public HideableMutableTreeNode(Object userObject, boolean allowsChildren) {
super(userObject, allowsChildren);
* Checks if the node is visible.
* @return true if the node is visible, else false
public boolean isVisible() {
return this.visible;
* Sets if the node is visible.
* @param v true if the node is visible, else false
public void setVisible(boolean v) {
this.visible = v;
// *** TreeNodeTreeModel ***
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
* <code>TreeNodeTreeModel</code> is an <code>AbstractTreeModel</code>
* implementation for <code>javax.swing.tree.TreeNode</code> objects.
public class TreeNodeTreeModel extends AbstractTreeModel {
* Creates a new <code>TreeNodeTreeModel</code> object.
* @param root the root node
public TreeNodeTreeModel(TreeNode root) {
super();
setRoot(root);
* Returns the parent of the child node.
* @param node the child node
* @return the parent or null if root
public Object getParent(Object node) {
if(node != getRoot() && (node instanceof TreeNode)) {
return ((TreeNode)node).getParent();
return null;
* Returns the child of parent at index index in the parent's child array.
* @param parent the parent node
* @param index the index
* @return the child or null if no children
public Object getChild(Object parent, int index) {
if(parent instanceof TreeNode) {
return ((TreeNode)parent).getChildAt(index);
return null;
* Returns the number of children of parent.
* @param parent the parent node
* @return the child count
public int getChildCount(Object parent) {
if(parent instanceof TreeNode) {
return ((TreeNode)parent).getChildCount();
return 0;
* Returns the index of child in parent.
* @param parent the parent node
* @param child the child node
* @return the index of the child node in the parent
public int getIndexOfChild(Object parent, Object child) {
if(parent instanceof TreeNode && child instanceof TreeNode) {
return ((TreeNode)parent).getIndex((TreeNode)child);
return -1;
* Returns true if node is a leaf.
* @param node the node
* @return true if the node is a leaf
public boolean isLeaf(Object node) {
if(node instanceof TreeNode) {
return ((TreeNode)node).isLeaf();
return true;
* Main method for testing.
* @param args the command-line arguments
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
root.add(new DefaultMutableTreeNode("child_1"));
DefaultMutableTreeNode c2 = new DefaultMutableTreeNode("child_2");
c2.add(new DefaultMutableTreeNode("child_2_A"));
c2.add(new DefaultMutableTreeNode("child_2_B"));
root.add(c2);
root.add(new DefaultMutableTreeNode("child_3"));
root.add(new DefaultMutableTreeNode("child_4"));
JTree tree = new JTree(new TreeNodeTreeModel(root));
f.getContentPane().add(new JScrollPane(tree));
f.pack();
f.setSize(300, 500);
f.show();
// *** AbstractTreeModel ***
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
public abstract class AbstractTreeModel implements TreeModel {
* The list of tree model listeners.
private Vector modelListeners = new Vector();
* The root object of the tree.
private Object root = null;
* Basic no-op constructor.
public AbstractTreeModel() {
* Gets the root object of the tree.
* @return the root object
public Object getRoot() {
return this.root;
* Sets the root object of the tree.
* @param r the root object
protected void setRoot(Object r) {
this.root = r;
* Gets the path to the root node for the specified object.
* @param node the root node
* @return the path to the object or <CODE>null</CODE>
public Object[] getPathToRoot(Object node) {
return getPathToRoot(node, 0);
* Gets the path to the root node for the specified object.
* @param node the root node
* @param i the current index
* @return the path to the object or <CODE>null</CODE>
private Object[] getPathToRoot(Object node, int i) {
Object anode[];
if(node == null) {
if(i == 0) {
return null;
anode = new Object[i];
} else {
i++;
if(node == getRoot()) {
anode = new Object[i];
} else {
anode = getPathToRoot(getParent(node), i);
anode[anode.length - i] = node;
return anode;
* Gets the parent object of the specified object. This method is not
* part of the <code>javax.swing.tree.TreeModel</code> interface, but is
* required to support the <code>getPathToRoot(Object)</code> method,
* which is widely used in this class. Therefore, it is important to
* correctly implement this method.
* @param obj the object
* @parma the parent object or null if no parent or invalid object
protected abstract Object getParent(Object obj);
* Adds a listener for the <CODE>TreeModelEvent</CODE> posted after the
* tree changes.
* @param l the tree model listener
public void addTreeModelListener(TreeModelListener l) {
modelListeners.addElement(l);
* Removes a listener previously added with addTreeModelListener().
* @param l the tree model listener
public void removeTreeModelListener(TreeModelListener l) {
modelListeners.removeElement(l);
* Forces the tree to reload. This is useful when many changes occur
* under the root node in the tree structure.
* <b>NOTE:</b> This will cause the tree to be collapsed. To maintain
* the expanded nodes, see the <code>getExpandedPaths(JTree)</code>
* and <code>expandPaths(JTree, ArrayList)</code> methods.
* @see #getExpandedPaths(JTree)
* @see #expandPaths(JTree, ArrayList)
public void reload() {
reload(getRoot());
* Forces the tree to repaint. This is useful when many changes occur
* under a specific node in the tree structure.
* <b>NOTE:</b> This will cause the tree to be collapsed below the
* updated node.
* @param node the node that changed
public void reload(Object node) {
if(node != null) {
TreePath tp = new TreePath(getPathToRoot(node));
fireTreeStructureChanged(new TreeModelEvent(this, tp));
* Messaged when the user has altered the value for the item identified
* by <CODE>path</CODE> to <CODE>newValue</CODE>.
* @param path the path to the changed object
* @param newValue the new value
public void valueForPathChanged(TreePath path, Object newValue) {
nodeChanged(path.getLastPathComponent());
* Notifies the tree that nodes were inserted. The index is looked up
* automatically.
* @param node the parent node
* @param child the inserted child node
public void nodeInserted(Object node, Object child) {
nodeInserted(node, child, -1);
* Notifies the tree that nodes were inserted.
* @param node the parent node
* @param child the inserted child node
* @param index the index of the child
public void nodeInserted(Object node, Object child, int index) {
if(index < 0) {
index = getIndexOfChild(node, child);
if(node != null && child != null && index >= 0) {
TreePath tp = new TreePath(getPathToRoot(node));
int[] ai = { index };
Object[] ac = { child };
fireTreeNodesInserted(new TreeModelEvent(this, tp, ai, ac));
* Notifies the tree that nodes were removed. The index is required
* since by this point, the object will no longer be in the tree.
* @param node the parent node
* @param child the removed child node
* @param index the index of the child
public void nodeRemoved(Object node, Object child, int index) {
if(node != null && child != null && index >= 0) {
TreePath tp = new TreePath(getPathToRoot(node));
int[] ai = { index };
Object[] ac = { child };
fireTreeNodesRemoved(new TreeModelEvent(this, tp, ai, ac));
* Notifies the tree that a node was changed.
* @param node the changed node
public void nodeChanged(Object node) {
if(node != null) {
TreePath tp = new TreePath(getPathToRoot(node));
fireTreeNodesChanged(new TreeModelEvent(this, tp, null, null));
* Fires "tree nodes changed" events to all listeners.
* @param event the tree model event
protected void fireTreeNodesChanged(TreeModelEvent event) {
for(int i = 0; i < modelListeners.size(); i++) {
((TreeModelListener)modelListeners.elementAt(i)).treeNodesChanged(event);
* Fires "tree nodes inserted" events to all listeners.
* @param event the tree model event
protected void fireTreeNodesInserted(TreeModelEvent event) {
for(int i = 0; i < modelListeners.size(); i++) {
((TreeModelListener)modelListeners.elementAt(i)).treeNodesInserted(event);
* Fires "tree nodes removed" events to all listeners.
* @param event the tree model event
protected void fireTreeNodesRemoved(TreeModelEvent event) {
for(int i = 0; i < modelListeners.size(); i++) {
((TreeModelListener)modelListeners.elementAt(i)).treeNodesRemoved(event);
* Fires "tree structure changed" events to all listeners.
* @param event the tree model event
protected void fireTreeStructureChanged(TreeModelEvent event) {
for(int i = 0; i < modelListeners.size(); i++) {
((TreeModelListener)modelListeners.elementAt(i)).treeStructureChanged(event);
* Records the list of currently expanded paths in the specified tree.
* This method is meant to be called before calling the
* <code>reload()</code> methods to allow the tree to store the paths.
* @param tree the tree
* @param pathlist the list of expanded paths
public ArrayList getExpandedPaths(JTree tree) {
ArrayList expandedPaths = new ArrayList();
addExpandedPaths(tree, tree.getPathForRow(0), expandedPaths);
return expandedPaths;
* Adds the expanded descendants of the specifed path in the specified
* tree to the internal expanded list.
* @param tree the tree
* @param path the path
* @param pathlist the list of expanded paths
private void addExpandedPaths(JTree tree, TreePath path, ArrayList pathlist) {
Enumeration enum = tree.getExpandedDescendants(path);
while(enum.hasMoreElements()) {
TreePath tp = (TreePath)enum.nextElement();
pathlist.add(tp);
addExpandedPaths(tree, tp, pathlist);
* Re-expands the expanded paths in the specified tree. This method is
* meant to be called before calling the <code>reload()</code> methods
* to allow the tree to store the paths.
* @param tree the tree
* @param pathlist the list of expanded paths
public void expandPaths(JTree tree, ArrayList pathlist) {
for(int i = 0; i < pathlist.size(); i++) {
tree.expandPath((TreePath)pathlist.get(i));Hey
I'm not trying to show anyone up here, but having just built a tree model for displaying an XML document in a tree, I thought this seemed like a neat exercise.
I implemented this very differently from the @OP. I only have one class, HiddenNodeTreeModel. All the hidden node data is stored in the model itself in my class. The advantage of what I've created is it will work with any TreeModel. The disadvantage is that I think it's not going to be very scalable - the additional computing to get the number of child nodes and to adjust indexes is heavy. So if you need a scalable solution definitely don't use this.
Anyway here you go
HiddenNodeTreeModel.java
======================
package tjacobs.ui.tree;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JTree;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import tjacobs.ui.WindowUtilities;
public class HiddenNodeTreeModel implements TreeModel {
TreeModel mModel;
ArrayList<Object> mHidden = new ArrayList<Object>();
public HiddenNodeTreeModel (TreeModel model) {
mModel = model;
public void addTreeModelListener(TreeModelListener arg0) {
mModel.addTreeModelListener(arg0);
private ArrayList<Integer> getHiddenChildren(Object parent) {
ArrayList<Integer> spots = new ArrayList<Integer>();
Iterator _i = mHidden.iterator();
while (_i.hasNext()) {
Object hidden = _i.next();
int idx = mModel.getIndexOfChild(parent, hidden);
if (idx != -1) {
spots.add(idx);
return spots;
public Object getChild(Object arg0, int index) {
ArrayList<Integer> spots = getHiddenChildren(arg0);
Collections.sort(spots);
Iterator<Integer> _i = spots.iterator();
while (_i.hasNext()) {
int num = _i.next();
if (num <= index) {
index++;
return mModel.getChild(arg0, index);
public int getChildCount(Object arg0) {
ArrayList list = getHiddenChildren(arg0);
System.out.println("size = " + list.size());
return mModel.getChildCount(arg0) - list.size();
public int getIndexOfChild(Object arg0, Object arg1) {
int index = mModel.getIndexOfChild(arg0, arg1);
ArrayList<Integer> spots = getHiddenChildren(arg0);
Collections.sort(spots);
Iterator<Integer> _i = spots.iterator();
int toSub = 0;
while (_i.hasNext()) {
int num = _i.next();
if (num <= index) {
toSub++;
return index - toSub;
public Object getRoot() {
// TODO Auto-generated method stub
return mModel.getRoot();
public boolean isLeaf(Object arg0) {
// TODO Auto-generated method stub
return mModel.isLeaf(arg0);
public void removeTreeModelListener(TreeModelListener arg0) {
mModel.removeTreeModelListener(arg0);
public void valueForPathChanged(TreePath arg0, Object arg1) {
mModel.valueForPathChanged(arg0, arg1);
public void hideNode(Object node) {
if (node instanceof TreePath) {
node = ((TreePath)node).getLastPathComponent();
mHidden.add(node);
public void showNode(Object node) {
mHidden.remove(node);
public void showAll() {
mHidden.clear();
* @param args
public static void main(String[] args) {
// TODO Auto-generated method stub
DefaultMutableTreeNode A = new DefaultMutableTreeNode("A");
DefaultMutableTreeNode B = new DefaultMutableTreeNode("B");
DefaultMutableTreeNode C = new DefaultMutableTreeNode("C");
DefaultMutableTreeNode D = new DefaultMutableTreeNode("D");
DefaultMutableTreeNode E = new DefaultMutableTreeNode("E");
DefaultMutableTreeNode F = new DefaultMutableTreeNode("F");
A.add(B);
B.add(C);
B.add(D);
B.add(E);
E.add(F);
DefaultTreeModel model = new DefaultTreeModel(A);
final HiddenNodeTreeModel hmodel = new HiddenNodeTreeModel(model);
final JTree tree = new JTree(hmodel);
JFrame jf = new JFrame("HiddenNodeTreeModel Test");
jf.add(tree);
JMenuBar bar = new JMenuBar();
jf.setJMenuBar(bar);
JMenu menu = new JMenu("Options");
bar.add(menu);
final JMenuItem hide = new JMenuItem("Hide");
final JMenuItem show = new JMenuItem("ShowAll");
menu.add(hide);
menu.add(show);
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == hide) {
hmodel.hideNode(tree.getSelectionPath());
tree.updateUI();
else {
hmodel.showAll();
tree.updateUI();
hide.addActionListener(al);
show.addActionListener(al);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setBounds(100,100,100,100);
jf.setVisible(true);
}
Maybe you are looking for
-
Short dump while executing info package in 3.5 data flow?
Hi, i am getting short dump while executing info package while executing info package. it was working perfectly 2 days back suddenly it is giving this problem. it is a full load for info object text data and i have only 600 records. when i tried with
-
Can anyone please suggest for the following query relating to OEDQ ?
I have to process 10M records through batch matching by Oracle EDQ. There will be 10 file(.csv) each size 1M. They will be placed landing area of EDQ one by one separately. Given, All 10 file should have same number of columns & same order of colu
-
How to put a table's all fields on a selection screen?
Hi, I am new here. I am currently create a report in which I need to put a transparent table's all fields on selection screen. Please give me hints about it. Thank you very much in advance. Tom
-
Elements Downloaded without photo creations folder in system files. unable to add actions
I have used Photoshop Elements 10 for some time now on my windows platform. I recently added it to my new macbook but as i went to add actions to the system file folder "photo creations" i noticed the folder is not there. I have tried pasting the act
-
Clean install leopard from 10.4.10
i would prefer clean install to leopard but i have a number of software license's that i have purchased. Is there any way to clean install leopard then copy back just the installed programs and the license's?