Update tree node
Hi,
I have a JTree, and at some point I need to update the icon of a node in the tree. FYI, I have a my own custom class which implements, TreeCellRenderer.
how can i do this??
thanks
bump
Similar Messages
-
Update tree node icon, better way?
Hi,.
I have my own custom renderer for my JTree....such as
public class MyTreeNodeRenderer extends JLabel implements TreeCellRenderer {
public Component getTreeCellRendererComponent(
JTree treeVal,
Object valueVal,
boolean selectedVal,
boolean expandedVal,
boolean leafVal,
int rowVal,
boolean hasFocusVal) {
MyTreeNode node = (MyTreeNode) valueVal;
// get the latest type for this node
node.type = getType(node);
if (node.type == 1) {
setIcon(TYPE1_ICON);
else {
setIcon(TYPE_BASIC_ICON);
return this;
}...intially the tree nodes have their icons, as they should...later on their "type" is updated...so instead of being 1..its now something else...so the icon should change.....but it doesnt occur fast enough...so i added this to my renderer
public void doRepaint() {
repaint();
myTree.repaint();
}basically anytime i needed to update the icon in the tree i called the doRepaint when i want the new icon to appear in the tree..that helped somewhat..but it is still kinda slow....any ideas how to do this?valueForPathChanged() serves different purposes as you can see from its description. You need to call treeModel.nodeChanged(node) after your node changed its "type". If you don't want to hold or don't have treeModel reference you could use tree classes from .useful library and be able to call nodeChanged() directly from a node that has been changed.
Denis Krukovsky
http://dotuseful.sourceforge.net/ -
Why I cannot edit and updat tree node in this program??
Dear Friends:
I have following code, it can be run ok,
I set it editable, I hope to edit at run time, but looks like I cannot edit,
what is wrong??
Can you help??
Thanks
package treeSelectionListener;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
public class SelectableTreeTest extends JFrame
public SelectableTreeTest(){
JPanel jp = new JPanel();
JPanel jp2 = new JPanel();
MyTree myTree= new MyTree();
MyTree myTree2= new MyTree();
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.setPreferredSize(new Dimension(600,400));
jp.setPreferredSize(new Dimension(600,400));
jp2.setPreferredSize(new Dimension(600,400));
myTree.setPreferredSize(new Dimension(600,400));
myTree2.setPreferredSize(new Dimension(600,400));
JScrollPane jsp = new JScrollPane();
jsp.setPreferredSize(new Dimension(600,400));
add(jsp, BorderLayout.CENTER);
jsp.setViewportView(tabbedPane);
jp.add(myTree);
jp2.add(myTree2);
tabbedPane.addTab("1st Tree", jp);
tabbedPane.addTab("2nd Tree", jp2);
public static void main(String[] args) {
JFrame frame = new SelectableTreeTest();
WindowUtilities.setNativeLookAndFeel();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
frame.pack();
frame.setVisible(true);
public class MyTree extends JTree implements TreeSelectionListener {
private JTree tree;
private JTextField currentSelectionField;
public MyTree() {
Container content = getContentPane();
DefaultMutableTreeNode root =
new DefaultMutableTreeNode("Root");
DefaultMutableTreeNode child;
DefaultMutableTreeNode grandChild;
for(int childIndex=1; childIndex<4; childIndex++) {
child = new DefaultMutableTreeNode("Child " + childIndex);
root.add(child);
for(int grandChildIndex=1; grandChildIndex<4; grandChildIndex++) {
grandChild =
new DefaultMutableTreeNode("Grandchild " + childIndex +
"." + grandChildIndex);
child.add(grandChild);
tree = new JTree(root);
tree.setEditable(true);
tree.addTreeSelectionListener(this);
content.add(new JScrollPane(tree), BorderLayout.CENTER);
currentSelectionField = new JTextField("Current Selection: NONE");
content.add(currentSelectionField, BorderLayout.SOUTH);
setSize(250, 275);
setVisible(true);
public void valueChanged(TreeSelectionEvent event) {
currentSelectionField.setText
("Current Selection: " +
tree.getLastSelectedPathComponent().toString());
}change this
tree = new JTree(root);
tree.setEditable(true);
tree.addTreeSelectionListener(this);to this
setEditable(true);
addTreeSelectionListener(this);and this
currentSelectionField.setText
("Current Selection: " +
tree.getLastSelectedPathComponent().toString());to this
currentSelectionField.setText
("Current Selection: " +
getLastSelectedPathComponent().toString());and remove this
private JTree tree; -
Invalid B-tree node size error & updating OS
I was toying around with the idea of updating my OS to 10.4 and increasing my storage capacity. A welcome upgrade to an old system that has been very good to me....until now.
The short version is that I am experiencing quite a bit of directory damage (for the full story, read below). After researching hundreds of posts here, I think my best bet is to purchase Disk Warrior. My question is, which version should a purchase? As a result of the work I've explained below, my system is currently running the version installed from my OSX Install CD. I'm not sure what version this is, but my Mac came with CDs for OS9, OSX, and an upgrade to 10.2.8. Is there a version of Disk Warrior that will support 10.2-10.4? I want to fix the current issues but still be able to use this software when (or IF) I upgrade.
I'm happy to provide any info needed and appreciate ANY help. Thanks,
On a routine startup I encountered the stalled progress indicator (spinning gear) and its been downhill from there. I've scoured the Mac forums here for possible fixes, but so far nothing has been able to completely solve my problem. Here's a brief rundown of what I have done so far:
1) Booted from OSX Install CD and ran disk utility. This verified I had catalog and node errors that could not be repaired.
2) Ran Apple Hardware test from CD. Everything was fine.
3) Ran TECHTool Pro that came with my AppleCare CD and identified similar errors but could not repair them. At this point I also got an "Invalid Sibling Link" error.
Finally I decided that the data I had saved on my HD was not crucial so I would attempt a reinstall of the OS and lose what was not backed up. So I:
5) Performed reinstall from OSX Install CD.
6) Ran Disk Utility, all was fine.
At this point I was able to run programs and boot up normally. Of course this was too good to be true, and it was, because subsequent restarts gave me even more errors! I was again experiencing the freeze at startup, although this time I was getting the Mac computer logo with smiley face icon for all eternity.
7) Again booted from OSX Install CD and ran Disk Utility. I'm now getting an "Invalid B-tree node size" error. I;ve tried all the cycles with repair utilities to no avail. I am also unable to start up in single user mode so I'm stuck.
iMac G4 Flat Panel Mac OS X (10.2.x) Purchased 2002
iMac G4 Flat Panel Mac OS X (10.2.x) Purchased 2002Thanks! I will order DW and give it a try...
I have run the Apple Hardware diagnostic CD twice (at different points in this process) and everything has come back cleanly. I am fairly certain this is a directory issue, but we'll wait and see. At the very least I will have DW to back up any future systems.
This is sortof off topic, but what is the general service fee for visiting the Genius Bar? I consulted a Mac pro there to discuss an upgrade to my system, but there was no charge. I find this hard to believe...does anyone know? I can't seem to find anything online... -
How to resize a custom tree node like you would a JFrame window?
Hello,
I am trying to resize a custom tree node like you would a JFrame window.
As with a JFrame, when your mouse crosses the Border, the cursor should change and you are able to drag the edge to resize the node.
However, I am faced with a problem. Border cannot detect this and I dont want to use a mouse motion listener (with a large number of nodes, I fear it will be inefficient, calculating every node's position constantly).
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.util.EventObject;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeSelectionModel;
public class ResizeNode extends JPanel {
AnilTreeCellRenderer2 atcr;
AnilTreeCellEditor2 atce;
DefaultTreeModel treeModel;
JTree tree;
DefaultMutableTreeNode markedNode = null;
public ResizeNode() {
super(new BorderLayout());
treeModel = new DefaultTreeModel(null);
tree = new JTree(treeModel);
tree.setEditable(true);
tree.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
tree.setCellRenderer(atcr = new AnilTreeCellRenderer2());
tree.setCellEditor(atce = new AnilTreeCellEditor2(tree, atcr));
JScrollPane scrollPane = new JScrollPane(tree);
add(scrollPane,BorderLayout.CENTER);
public void setRootNode(DefaultMutableTreeNode node) {
treeModel.setRoot(node);
treeModel.reload();
public static void main(String[] args){
ResizeNode tb = new ResizeNode();
tb.setPreferredSize(new Dimension(400,200));
JFrame frame = new JFrame("ResizeNode");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(tb);
frame.setSize(400, 200);
frame.pack();
frame.setVisible(true);
tb.populate();
private void populate() {
TextAreaNode2 r = new TextAreaNode2(this);
setRootNode(r);
TextAreaNode2 a = new TextAreaNode2(this);
treeModel.insertNodeInto(a, r, r.getChildCount());
class AnilTreeCellRenderer2 extends DefaultTreeCellRenderer{
TreeBasic panel;
DefaultMutableTreeNode currentNode;
public AnilTreeCellRenderer2() {
super();
public Component getTreeCellRendererComponent
(JTree tree, Object value, boolean selected, boolean expanded,
boolean leaf, int row, boolean hasFocus){
TextAreaNode2 currentNode = (TextAreaNode2)value;
NodeGUI2 gNode = (NodeGUI2) currentNode.gNode;
return gNode.box;
class AnilTreeCellEditor2 extends DefaultTreeCellEditor{
DefaultTreeCellRenderer rend;
public AnilTreeCellEditor2(JTree tree, DefaultTreeCellRenderer r){
super(tree, r);
rend = r;
public Component getTreeCellEditorComponent(JTree tree, Object value,
boolean isSelected, boolean expanded, boolean leaf, int row){
return rend.getTreeCellRendererComponent(tree, value, isSelected, expanded,
leaf, row, true);
public boolean isCellEditable(EventObject event){
return true;
class NodeGUI2 {
final ResizeNode view;
Box box = Box.createVerticalBox();
final JTextArea aa = new JTextArea( 1, 5 );
final JTextArea aaa = new JTextArea( 1, 8 );
NodeGUI2( ResizeNode view_ ) {
this.view = view_;
box.add( aa );
aa.setBorder( BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.GREEN ) );
box.add( aaa );
box.setBorder( BorderFactory.createMatteBorder( 5, 5, 5, 5, Color.CYAN ) );
private Dimension getEditorPreferredSize() {
Insets insets = box.getInsets();
Dimension boxSize = box.getPreferredSize();
Dimension aaSize = aa.getPreferredSize();
Dimension aaaSize = aaa.getPreferredSize();
int height = aaSize.height + aaaSize.height + insets.top + insets.bottom;
int width = Math.max( aaSize.width, aaaSize.width );
if ( width < boxSize.width )
width += insets.right + insets.left + 3; // 3 for cursor
return new Dimension( width, height );
class TextAreaNode2 extends DefaultMutableTreeNode {
NodeGUI2 gNode;
TextAreaNode2(ResizeNode view_) {
gNode = new NodeGUI2(view_);
}the node on the tree is only painted on using the
renderer to do the painting work. A mouse listener
has to be added to the tree, and when moved over an
area, you have to determine if you are over the
border and which direction to update the cursor and
to know which way to resize when dragged. One of the
BasicRootPaneUI has some code that can help determine
that.Thanks for replying. What is your opinion on this alternative idea that I just had?
I am wondering if it might be easier to have a toggle button in the node that you click when you want to resize the node. Then a mouse-down and dragging the mouse will resize the node. Mouse-up will reset the toggle button, and so will mouse down in an invalid area.
Anil -
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);
} -
How-to synchronize edit forms for a single View Object tree node entrie
Hi all,
I created a tree from a single View Object,
follow this [http://www.oracle.com/technetwork/developer-tools/adf/learnmore/32-tree-table-from-single-vo-169174.pdf]
then i want to create and synchronize edit forms for tree node entries,
follow this [http://www.oracle.com/technetwork/developer-tools/adf/learnmore/50-synchromize-form-treeselection-169192.pdf]
but it not working when i click child node!!
i found the latter tree from many View Object ,but the former tree from single View Object.
what should i do?
Thanks in advanceHi,
say the tree is built from ViewObject1. In the AM model, create a second View Object instance for this. Say ViewObject2. Create the form from ViewObject2 and the tree from ViewObject1. When creating the tree, use the"Target Data Source" option at the bottom to reference the iterator of ViewObject2. Then create a PartialTrigger on the paneFormLayout that holds the synch form. In the partial trigger property, reference the tree so that when the tree selection changes, the form is updated. Then create a PartialTrigger property on the tree and point it to the submit button of the form so you can show updated values in the tree.
Frank -
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 -
How do we make a newly created tree-node the currently selected one?
Hi,
We are using JHeadstart 10.1.3 - Tree Generation. We are running into several issues with the trees, especially upon creation of new tree nodes. The Form in our Tree-Form page is Saved. At that point, we would like the new node to be the selected node in the tree (and also in the tree bean).
How do you believe can we do this? Right now, after creating the new node, we have no node selected - although it seems that the new node is selected as the normally synchronized form on the right shows that node.
Thanks for any suggestions!
LucasSteven,
I had not upgraded to Service Update 1 - was using Build 91. After upgrading, I see some difference, but not entirely the result I was looking for.
In a Tree-Form page on Employees, when I added an employee at the same level it still did not seem to be automatically selected.
Was wondering whether perhaps this has to do with the following comment from the source code:
// this happens when posting back to the same node level in the tree:
// the root node binding has no children in that case, causing derivation
// of focus row key to fail, have to find out why root node children
// are lost. Work around for now: return the focus row key as set by
// the user clikcing on the nodeIf not, can you explain what this comment refers to?
thanks for your help.
Lucas -
Lables fully not visible in the Tree node
Hi friends,
Some text in the tree node were not visible fully.
example : instead of documentation, it just displays doc...
instead of Library, it just displays lib....
And the problem doesn't appear continuously. Sometime the text is fully visible and some time it doesn't.
If I expand the tree the text is fully visible again. I couldn't reproduce the issue continuously. I tried tree.repaint(), tree.validate(), tree.invalidate(), tree.revaidate(). but it didn't work.
Anybody can suggest what would be the exact problem?
Thanks in advance.It's hard to say without seeing the code for TreeTable. But they probably have something like an addNode mothod for the TreeTableNode which will take care of all the updates for you. If you want to do it youself, you will probably have to get the data Model (tree.getModel()???)behind the TreeTable and use one of the fire... methods on it like fireRowChanged(???) or fireTableChanged(???). I would suspect Sun would do it this way.
-
Select tree node in tree component
hi,
i am developing a web site which has a site map as a tree component, the sitemap is a inserted in a page fragment, users could click tree nodes to go to corresponding pages. also on other pages, i have next and previous buttons which allow users to navigate through pages. the question is how can i update the tree component when users navigate using the next and previous buttons so that the correct tree node is highlighted?
i tried to use the selected property for the tree component, but it does not do anything.
thanks,
leeHi,
Duplicate thread of
http://swforum.sun.com/jive/thread.jspa?threadID=64518
MJ -
Invoking taskflow dynamically on to dynamic Region from Tree Nodes
Hello,
I have a tree , each node represents application task flow want to invoke the corresponding task flow when node is clicked into same Dynamic Region, is it possible?
Any idea will be greatly appreciated.
Thanks
RamThanks for quick response, I have a mouse double click event on tree node to fire task flow.
I added a method in region bean to change and update the view scope from treeListener.
public void handleTreeDoubleClick(ClientEvent ce){
System.out.println(ce.getComponent().toString());
RichTree tree = (RichTree)ce.getComponent();
System.out.println("double click");
System.out.println("sNodeValue : menuTreeSelectionListener "+sNodeValue);
FacesContext fctx = FacesContext.getCurrentInstance();
String rowKeyString = sNodeValue;
RegionBean regionBean = new RegionBean();
// regionBean.setDynamicTaskFlowId(TaskFlowId.parse(""));
System.out.println("changing the task flow ...");
regionBean.refreshRegion(TaskFlowId.parse("/WEB-INF/task-flow-welcome.xml#task-flow-welcome"));
public void refreshRegion(TaskFlowId TaskFlowId) {
System.out.println("taskflow id :"+TaskFlowId.toString());
this.setDynamicTaskFlowId(TaskFlowId);
oracle.adf.view.rich.context.AdfFacesContext adfFacesContext = oracle.adf.view.rich.context.AdfFacesContext.getCurrentInstance();
adfFacesContext.getPageFlowScope().put("CurrentTaskflowId", TaskFlowId);
But region is not getting refrehed with new taskflow id:
console output.............
changing the task flow ...
taskflow id :/WEB-INF/task-flow-welcome.xml#task-flow-welcome
any thoughts?
Thanks
Ram -
How to get Value of tree node without Reload Page
hi,
i worked with apex 4.2 and i created Tree and tabular form to retrieve the date according the value of tree select node the code of tree something like this
select case when connect_by_isleaf = 1 then 0
when level = 1 then 1
else -1
end as status,
level,
"ENAME" as title,
null as icon,
"EMPNO" as value,
null as tooltip,
'f?p=36648:34:5234984107903::::P40_SELECTED_NODE:'||empno as link
from "DEPT"."EMP"
start with "MGR" is null
connect by prior "EMPNO" = "MGR"
order siblings by "ENAME
and i put Selected Node Page Item: P40_SELECTED_NODE . the tree worked good and retrieve the data into tabular form according to tree node value
my Question :
1- i want to retrieve the data without submit the page where each time i select value from tree make page reload to update the tabular form with new value ,there is any way to pass the value of tree node to P40_SELECTED_NODE item and refresh tabular form without page reload .
2- i want when selected from tree run page process according to value of tree node i tray to create Dynamic action with *(jquery selector : div.tree li>a)* but the Value of node incorrect.
Regards
Ahmed;look at this link
Re: How to get Value of tree node without Reload Page ..! -
Commandtoolbarbutton enabling/disabling based on tree node selection
i am using the tree tag to generate a set of nodes and every node is a command link.... i have a set of commandtoolbarbuttons on top of the tree... the functionality i am trying to obtain is on press of the tree node( i.e, command link ) the commantoolbarbuttons are enabled or disabled.. on press of link i am able to get the tree node selected in the backing bean, and also i am setting some variables for the "disabled" attribute of commandtoolbarbutton. The problem i am facing here is i have a partialtrigger attribute in the commandtoolbarbutton pointing to the commandlink id. But the partial trigger is unable to identify the command link id outside the tree. And i cannot put the commandtoolbar buttons inside the tree...
Can anyone please let me know how can i resolve this?? or is there anyother approach??
The source code is as mentioned below...
<af:panelGroupLayout layout="horizontal" halign="right">
<f:facet name="separator">
<af:spacer width="5px"/>
</f:facet>
<af:toolbox id="mainTab_box" >
<af:toolbar id="mainTab_bar">
<af:spacer width="80"/>
<af:commandToolbarButton icon="/resources/images/new_ena.png" partialSubmit="true"
shortDesc="New" id="ctb1_mainTab" disabled="#{nodeSelectionHandler.createToolbar}" partialTriggers="cl1"/>
<af:commandToolbarButton icon="/resources/images/update_ena.png" partialSubmit="true"
shortDesc="Update" id="ctb2_mainTab" disabled="#{nodeSelectionHandler.editToolbar}" partialTriggers="cl1"/>
<af:commandToolbarButton icon="/resources/images/delete_ena.png" partialSubmit="true"
shortDesc="Delete" id="ctb3_mainTab" disabled="#{nodeSelectionHandler.cancelToolbar}" partialTriggers="cl1"/>
<af:commandToolbarButton icon="/resources/images/importIcon.png" partialSubmit="true"
shortDesc="Import" id="ctb4_mainTab" disabled="#{nodeSelectionHandler.exportToolbar}" partialTriggers="cl1"/>
<af:commandToolbarButton icon="/resources/images/exportIcon.png" partialSubmit="true"
shortDesc="Export" id="ctb5_mainTab" disabled="#{nodeSelectionHandler.importToolbar}" partialTriggers="cl1"/>
</af:toolbar>
</af:toolbox>
</af:panelGroupLayout>
<af:panelGroupLayout layout="scroll">
<af:tree var="node"
value="#{browserTreeModel}"
id="browsertree" inlineStyle="min-width:200px;min-height:400px;width:100%;height:100%"
rowSelection="single" clientComponent="true" contentDelivery="immediate"
>
<f:facet name="nodeStamp">
<af:panelGroupLayout id="pgl10">
<af:image id="nodeIcon"
inlineStyle="margin-right:3px; vertical-align:middle; height:16px; width:16px;"
shortDesc="directory icon" rendered="#{node.destination != null}"
source="#{node.destination}"/>
<af:commandLink text="#{node.text}"
id="cl1"
disabled="false" partialSubmit="true"
actionListener="#{nodeSelectionHandler.selectionPerformed}" >
<f:attribute name="nodeId" value="#{node.id}"/>
<f:attribute name="operation" value="#{node.associatedOperation}"/>
</af:commandLink>
</af:panelGroupLayout>
</f:facet>
</af:tree>
</af:panelGroupLayout>With apologies, you're not aware of ELUtils class devised by Steve Muench:
package view;
import javax.faces.context.FacesContext;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;
public class ELUtils {
public static boolean test(String booleanExpr) {
return Boolean.TRUE.equals(get(booleanExpr));
public static String getAsStringWithDefault(String expr, String defaultExpr) {
return (String)getWithDefault(expr, defaultExpr);
public static String getAsString(String expr) {
return (String)get(expr);
public static Integer getAsInteger(String expr) {
return (Integer)get(expr);
public static Object get(String expr) {
FacesContext fc = FacesContext.getCurrentInstance();
ValueBinding vb = fc.getApplication().createValueBinding(expr);
return vb.getValue(fc);
public static Object getWithDefault(String expr, String defaultExpr) {
Object exprVal = get(expr);
return exprVal != null ? exprVal : get(defaultExpr);
public static void set(String expr, String value) {
Object valToSet = value;
if (isELExpr(value)) {
valToSet = get(value);
set(expr, valToSet);
public static void set(String expr, Object value) {
FacesContext fc = FacesContext.getCurrentInstance();
ValueBinding vb = fc.getApplication().createValueBinding(expr);
vb.setValue(fc, value);
private static boolean isELExpr(Object o) {
if (o instanceof String) {
String str = (String)o;
str.trim();
return str.startsWith("#{") && str.endsWith("}");
return false;
public static Object invokeMethod(String expr, Class[] paramTypes, Object[] params) {
FacesContext fc = FacesContext.getCurrentInstance();
MethodBinding mb = fc.getApplication().createMethodBinding(expr, paramTypes);
return mb.invoke(fc, params);
public static Object invokeMethod(String expr, Class paramType, Object param) {
return invokeMethod(expr, new Class[] { paramType }, new Object[] { param });
}Try that.
CM. -
Loading Tree Node/Leaf causing numerous errors
I am loading a tree with UNSPSC codes using an application engine program with code borrowed from a delivered app engine program. The code loads most of the codes, however I receive numerous errors as follows:
Node not Found (92,3209) - I get this a lot but the data still loads in both PSTREENODE and PSTREELEAF
Return: 805 - ORA-00001: unique constraint (FS.PS_PSTREELEAF) violated
Failed SQL stmt:UPDATE PSTREELEAF SET TREE_NODE_NUM = :1, OLD_TREE_NODE_NUM = 'N' WHERE SETID = :2 AND SETCNTRLVALUE = :3 AND TREE_NAME = :4 AND EFFDT = TO_DATE(:5,'YYYY-MM-DD') AND OLD_TREE_NODE_NUM = 'Y' AND TREE_NODE_NUM = :6
Tree Save error (92,3061)
-- This error will rollback my changes to my last commit point, which, because of this error, I am committing after every value (saving tree, closing tree, and reopening the tree).
Node index error (0,0)
Node insert error (0,0)
-- These errors still allow me to enter the data.
A node without a parent was detected: %1 (25,22)
-- This error causes an abend.
The code used to update the tree is very simple (this code was copied verbatim from PV_CP_LOAD along with additional functions):
REM ****************************************************************************************;
Function AddToTree(&CAT_ID, &CAT_ID_PAR, &CAT_NAME, &ACCOUNT, &SIBLING)
REM ****************************************************************************************;
rem Add child to parent;
If &CAT_ID <> &FIRST_NODE Then
&MYNODE = &MS_TREE.FindNode(&CAT_ID, "");
If None(&MYNODE) Then
&MYNODE = &MS_TREE.FindNode(&CAT_ID_PAR, "");
If All(&MYNODE) Then
&NEWNODE = &MYNODE.InsertChildNode(&CAT_ID);
If All(&NEWNODE) Then
&NEWLEAF = &NEWNODE.INSERTDYNCHILDLEAF();
&NodeCount = &NodeCount + 1;
End-If;
End-If;
Else
rem in case tree node is already there, but category isn't;
rem addcategories(&CAT_ID, &CAT_NAME, &ACCOUNT, &CATEGORY_REC);
End-If;
End-If;
End-Function;
I am getting roughly 50% failure rate.
Is there a database issue? Configuration of my Tree?What I discovered is that Node API method INSERTDYNCHILDLEAF tries to re-number all the leafs inserted each time it is called. However, it doesn't check to see if the TREE_NODE_NUM already exists. Since the TREE_NODE_NUM column is a key, it causes a unique constraint error.
I pointed this out to Oracle, however, since I was using this function in a custom app engine program, they would not look at the problem. My app engine trace clearly showed the problem.
I ended up re-writing the program to insert directly into the PSTREENODE and PSTREELEAF tables, controlling the TREE_NODE_NUM and PARENT_NODE_NUM columns myself. The result was a tree with 20499 rows with 0 audit errors.
Maybe you are looking for
-
Oracle 10g R2 with ASM Installation Problem on RHEL AS 4.5 for Itanium
Greetings to All ! I am trying to install Oracle 10g R2 , but when I am executing 'runInstaller', I am getting the following prolem and OUI dosen't start. The message is:- # An unexpected error has been detected by HotSpot Virtual Machine: # SIGILL (
-
Unable to execute Web Service from SSRS Dataset
Hi, I am unable to access a Web Service to execute Dataset from MS SSRS. I have created a Dataset that refers to a WebService as a Query. The dataset and Query runs well in DEV environment. However, the following error message is displayed when exec
-
Movie with flv only runs locally
Greetings- I built a Flash movie using the FLVPlayback component and attached a .flv movie in its source. As far as I know the movie file is not embedded in the timeline, it is attached as a separate file for reference to the .swf. I published the mo
-
Drag and drop counter which activates a animation when certain number is reached
Hi there guys, I was wondering if anyone could help me with this problem, I'm using adobe edge to create a drag and drop game and I want edge to use a counter to track how many draggable parts have been dropped in their repective targets, when a
-
Missing lib libcwait.so in OEL 6.0
I updated a development machine from OEL 4.0 to OEL 6.0 (64 bit) and a script I used and worked before complains about a missing library: /usr/lib/libcwait.so Any ideas how can I replace this library? Or maybe in OEL 6.0 there is a different lib doin