Selection in JTreeTables

I'm trying to programmatically select nodes within my JTreeTable, with zero-success...
I imagined the following would be fine for rendering the selection.
JTree tree = treeTable.getTree();
tree.setExpandsSelectedPaths(true);
treePath = treePath.pathByAddingChild(someObject);
tree.setSelectionPath(treePath);
The parent node is properly expanded and the new child becomes visible, however, there is no selection.
Any help very welcome.
thanks,
ian

Hi monicaba!
I've had the same problem. The Method setSelectionPath() did not do what it should. I read your articles and tried out your suggestion to comment the delayedFireTableDataChanged() line. But it did not solve the problem.
Anyway, I found another way to make it work and I want to share it with you ;-) :
After inserting the new node and after updating the display via calling fireTreeNodesInserted(), I return the new tree path to the new child (addChildToParent() is my own method of the tree table model):
// Insert child into tree table, update the display via
// fireTreeNodesInserted() and return the new inserted tree path
_selectionPath = treeTableModel.addChildToParent(...);
Then I call the invokeLater() method of SwingUtilities to select the new path (Jtretbl_Data is my JTreeTable!):
// Make the new path selected
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Jtretbl_Data.getTree().setSelectionPath(_selectionPath);
The disadvantage of this is that the variable _selectionPath has to be a member variable of my applet. Perhaps I could improve that point.
Best regards,
Peter

Similar Messages

  • How to enable programmatic tree path selection in JTreeTable?

    Post about usage of JTreeTable provided by Philip Milne.
    A problem I met is that one can not set a tree path selected programmatically. It seems that the installing of ListToTreeSelectionModelWrapper disables this action or the selection is done at first but later it is unselected again. It is very hard for me to understand the source code of JTreeTable and it is impossible for me to alter the ListToTreeSelectionModelWrapper to meet my need. Perhaps someone else there has also confronted such problem before. You would be very nice to inform me some tips.
    Thanks!

    Hi,
    You can enable the self-site creation using PowerShell by using the following command.
    $webApplication = Get-SPWebApplication <<http://WebApplication>>
    $webApplication.SelfServiceSiteCreationEnabled =$True
    $webApplication.Update()
    Please mark it answered, if your problem resolved.

  • JTreeTable - Dynamic Child Loading - Selection problem

    Hi,
    I'm using JTreeTable Example 3 for my application.
    I've hidded the root and I am loading the child nodes for the second level nodes(parent) dynamically using the treeWillExpand() method . So my Model will be updated dynamically during runtime.
    The problem is, the selection of the TreeTable is not working properly after the expansion. Please throw some light on this issue.
    Thanks in advance
    Your
    Arun

    try to invoke reload(); on your treeModel ...
    i had this problem too only if the root is hided ...

  • JTreeTable selection problem

    hi
    1.I am using the JSort treetable from the site:http://cal007300.student.utwente.nl/treetables/
    (example3) and i found that there is a bug of row selection in the table:
    not all the cells in the row are marked - evetu time i click on a certain cell several cells are marked (sometimes cells that r not connected to each other).
    Does anyone can give me a key to solving this problem?
    2.I want to add a pop up menu to the tree (opened on right click)- is it possible to add the table another mouse listener (i guess there is one that pass the mouse events to the tree)?
    thabks in advance
    liat

    try to invoke reload(); on your treeModel ...
    i had this problem too only if the root is hided ...

  • JTreeTable row selection

    Hi Guys,
    Is there a way i can select the row in a table, without actually passing the focus to that row. I want to programatically highlight the row instead of selecting it. please help me in this regard
    -nicedude

    Try putting, object."requestFocus()" right after you select the row in the table where object is a default object that you do not mind that it has the focus.

  • JTree custom renderer setting selection background color problem

    Hi,
    I have a JTree with a custom icon renderer that displays an icon. The JTree is part of a TreeTable component. Iam having a problem setting the selection background uniformly for the entire row. There is no problem when there is no row selected in the JTable.
    My present code looks like this:
    Iam overriding paint in my renderer which extends DefaultCellRenderer.
           super.paint(g);
            Color bColor = null;
            if(!m_selected) {
                 if(currRow % 2 == 0) {
                      bColor = Color.WHITE;
                 } else {
                                                    bColor = backColor;
            } else {
                 bColor = table.getSelectionBackground();                  bColor = getRowSelectionColor();
         if(bColor != null) {
                           g.setColor(bColor);
             if(!m_selected) {
                   g.setXORMode(new Color(0xFF, 0xFF, 0xFF));
             } else {
                 g.setXORMode(new Color(0x00, 0x00, 0x00));
                  I have a color I arrive at using some algorithm that I want using method getRowSelectionColor(). The other cells in the row have this color. But the cell containing the tree node shows different color. Iam not able to arrive at the right combination of the color to set and the xor color so my tree node also looks like the other cells in the row.
    It is not a problem really as the table still looks good. Its just that the tree node looks like it has been highlighted and this might cause a problem when a table cell is highlighed later on in the application ( two cells in the row would be highlighted causing confusion).
    Any help would be appreciated.
    Regards,
    vidyut

    Hi Camickr,
    Thanks for the reply. Iam sorry I didn't include the sources the first time around. There were too many of them. I have created a small, self-contained, compilable program that demonstrates the problem and including it herewith. Still there's quite many files but they are all needed Iam afraid. The only one you will have to concern yourself fior this problem is the file IconRenderer.java. The treenode background and the other cells background are not in sync when table row is not selected in this example though. But they are in my real program. I just need them to be in sync i.e have the same background color when the row is selected.
    Your help would be very much appreciated.
    These are the files that are included below:
    1. AbstractTreeTableModel.java
    2. Bookmarks.java
    3. BookmarksModel.java
    4. DynamicTreeTableModel.java
    5. IconRenderer.java
    6. IndicatorRenderer.java
    7. JTreeTable.java
    8. TreeTableExample3.java (contains main)
    9. TreeTableModel.java
    10. TreeTableModelAdapter.java
    The copyright and javadocs information has been stripped for clarity.
    cheers,
    vidyut
    // AbstractTreeTableModel.java BEGIN
    import javax.swing.tree.*;
    import javax.swing.event.*;
    public abstract class AbstractTreeTableModel implements TreeTableModel {
        protected Object root;    
        protected EventListenerList listenerList = new EventListenerList();
        public AbstractTreeTableModel(Object root) {
            this.root = root;
        // Default implementations for methods in the TreeModel interface.
        public Object getRoot() {
            return root;
        public boolean isLeaf(Object node) {
            return getChildCount(node) == 0;
        public void valueForPathChanged(TreePath path, Object newValue) {}
        // This is not called in the JTree's default mode:
        // use a naive implementation.
        public int getIndexOfChild(Object parent, Object child) {
            for (int i = 0; i < getChildCount(parent); i++) {
             if (getChild(parent, i).equals(child)) {
                 return i;
         return -1;
        public void addTreeModelListener(TreeModelListener l) {
            listenerList.add(TreeModelListener.class, l);
        public void removeTreeModelListener(TreeModelListener l) {
            listenerList.remove(TreeModelListener.class, l);
        protected void fireTreeNodesChanged(Object source, Object[] path,
                                            int[] childIndices,
                                            Object[] children) {
            // Guaranteed to return a non-null array
            Object[] listeners = listenerList.getListenerList();
            TreeModelEvent e = null;
            // Process the listeners last to first, notifying
            // those that are interested in this event
            for (int i = listeners.length-2; i>=0; i-=2) {
                if (listeners==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
    protected void fireTreeNodesInserted(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
    protected void fireTreeNodesRemoved(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
    protected void fireTreeStructureChanged(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
    // Default impelmentations for methods in the TreeTableModel interface.
    public Class getColumnClass(int column) { return Object.class; }
    public boolean isCellEditable(Object node, int column) {
    return getColumnClass(column) == TreeTableModel.class;
    public void setValueAt(Object aValue, Object node, int column) {}
    // Left to be implemented in the subclass:
    * public Object getChild(Object parent, int index)
    * public int getChildCount(Object parent)
    * public int getColumnCount()
    * public String getColumnName(Object node, int column)
    * public Object getValueAt(Object node, int column)
    // AbstractTreeTableModel.java END
    // Bookmarks.java BEGIN
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.text.*;
    import javax.swing.text.html.*;
    import javax.swing.text.html.parser.*;
    public class Bookmarks {
    /** The root node the bookmarks are added to. */
    private BookmarkDirectory root;
    * Creates a new Bookmarks object, with the entries coming from
    * <code>path</code>.
    public Bookmarks(String path) {
         root = new BookmarkDirectory("Bookmarks");
         if (path != null) {
         parse(path);
    * Returns the root of the bookmarks.
    public BookmarkDirectory getRoot() {
         return root;
    protected void parse(String path) {
         try {
         BufferedReader reader = new BufferedReader(new FileReader
                                       (path));
         new ParserDelegator().parse(reader, new CallbackHandler(), true);
         catch (IOException ioe) {
         System.out.println("IOE: " + ioe);
         JOptionPane.showMessageDialog(null, "Load Bookmarks",
                             "Unable to load bookmarks",
                             JOptionPane.ERROR_MESSAGE);
    private static final short NO_ENTRY = 0;
    private static final short BOOKMARK_ENTRY = 2;
    private static final short DIRECTORY_ENTRY = 3;
    private class CallbackHandler extends HTMLEditorKit.ParserCallback {
         /** Parent node that new entries are added to. */
         private BookmarkDirectory parent;
         /** The most recently parsed tag. */
         private HTML.Tag tag;
         /** The last tag encountered. */
         private HTML.Tag lastTag;
         * The state, will be one of NO_ENTRY, DIRECTORY_ENTRY,
    * or BOOKMARK_ENTRY.
         private short state;
         * Date for the next BookmarkDirectory node.
         private Date parentDate;
         * The values from the attributes are placed in here. When the
         * text is encountered this is added to the node hierarchy and a
    * new instance is created.
         private BookmarkEntry lastBookmark;
         * Creates the CallbackHandler.
         public CallbackHandler() {
         parent = root;
         lastBookmark = new BookmarkEntry();
         // HTMLEditorKit.ParserCallback methods
         * Invoked when text in the html document is encountered. Based on
         * the current state, this will either: do nothing
    * (state == NO_ENTRY),
         * create a new BookmarkEntry (state == BOOKMARK_ENTRY) or
    * create a new
         * BookmarkDirectory (state == DIRECTORY_ENTRY). If state is
    * != NO_ENTRY, it is reset to NO_ENTRY after this is
    * invoked.
    public void handleText(char[] data, int pos) {
         switch (state) {
         case NO_ENTRY:
              break;
         case BOOKMARK_ENTRY:
              // URL.
              lastBookmark.setName(new String(data));
    parent.add(lastBookmark);
    lastBookmark = new BookmarkEntry();
              break;
         case DIRECTORY_ENTRY:
              // directory.
              BookmarkDirectory newParent = new
                   BookmarkDirectory(new String(data));
              newParent.setCreated(parentDate);
              parent.add(newParent);
              parent = newParent;
              break;
         default:
              break;
    state = NO_ENTRY;
         * Invoked when a start tag is encountered. Based on the tag
         * this may update the BookmarkEntry and state, or update the
         * parentDate.
         public void handleStartTag(HTML.Tag t, MutableAttributeSet a,
                        int pos) {
         lastTag = tag;
         tag = t;
         if (t == HTML.Tag.A && lastTag == HTML.Tag.DT) {
    long lDate;
              // URL
              URL url;
              try {
              url = new URL((String)a.getAttribute(HTML.Attribute.HREF));
              } catch (MalformedURLException murle) {
              url = null;
              lastBookmark.setLocation(url);
              // created
              Date date;
              try {
    lDate = Long.parseLong((String)a.getAttribute("add_date"));
    if (lDate != 0l) {
    date = new Date(1000l * lDate);
    else {
    date = null;
              } catch (Exception ex) {
              date = null;
              lastBookmark.setCreated(date);
              // last visited
              try {
    lDate = Long.parseLong((String)a.
    getAttribute("last_visit"));
    if (lDate != 0l) {
    date = new Date(1000l * lDate);
    else {
    date = null;
              } catch (Exception ex) {
              date = null;
              lastBookmark.setLastVisited(date);
              state = BOOKMARK_ENTRY;
         else if (t == HTML.Tag.H3 && lastTag == HTML.Tag.DT) {
              // new node.
              try {
              parentDate = new Date(1000l * Long.parseLong((String)a.
                                  getAttribute("add_date")));
              } catch (Exception ex) {
              parentDate = null;
              state = DIRECTORY_ENTRY;
         * Invoked when the end of a tag is encountered. If the tag is
         * a DL, this will set the node that parents are added to the current
         * nodes parent.
         public void handleEndTag(HTML.Tag t, int pos) {
         if (t == HTML.Tag.DL && parent != null) {
              parent = (BookmarkDirectory)parent.getParent();
    public static class BookmarkDirectory extends DefaultMutableTreeNode {
         /** Dates created. */
         private Date created;
         public BookmarkDirectory(String name) {
         super(name);
         public void setName(String name) {
         setUserObject(name);
         public String getName() {
         return (String)getUserObject();
         public void setCreated(Date date) {
         this.created = date;
         public Date getCreated() {
         return created;
    public static class BookmarkEntry extends DefaultMutableTreeNode {
         /** User description of the string. */
         private String name;
         /** The URL the bookmark represents. */
         private URL location;
         /** Dates the URL was last visited. */
         private Date lastVisited;
         /** Date the URL was created. */
         private Date created;
         public void setName(String name) {
         this.name = name;
         public String getName() {
         return name;
         public void setLocation(URL location) {
         this.location = location;
         public URL getLocation() {
         return location;
         public void setLastVisited(Date date) {
         lastVisited = date;
         public Date getLastVisited() {
         return lastVisited;
         public void setCreated(Date date) {
         this.created = date;
         public Date getCreated() {
         return created;
         public String toString() {
         return getName();
    // Bookmarks.java END
    // BookmarksModel.java BEGIN
    import java.util.Date;
    public class BookmarksModel extends DynamicTreeTableModel {
    * Names of the columns.
    private static final String[] columnNames =
    { "Name", "Location", "Last Visited", "Created" };
    * Method names used to access the data to display.
    private static final String[] methodNames =
    { "getName", "getLocation", "getLastVisited","getCreated" };
    * Method names used to set the data.
    private static final String[] setterMethodNames =
    { "setName", "setLocation", "setLastVisited","setCreated" };
    private static final Class[] classes =
    { TreeTableModel.class, String.class, Date.class, Date.class };
    public BookmarksModel(Bookmarks.BookmarkDirectory root) {
         super(root, columnNames, methodNames, setterMethodNames, classes);
    public boolean isCellEditable(Object node, int column) {
         switch (column) {
         case 0:
         // Allow editing of the name, as long as not the root.
         return (node != getRoot());
         case 1:
         // Allow editing of the location, as long as not a
         // directory
         return (node instanceof Bookmarks.BookmarkEntry);
         default:
         // Don't allow editing of the date fields.
         return false;
    // BookmarksModel.java END
    // DynamicTreeTableModel.java BEGIN
    import java.lang.reflect.*;
    import javax.swing.tree.*;
    public class DynamicTreeTableModel extends AbstractTreeTableModel {
    /** Names of the columns, used for the TableModel getColumnName method. */
    private String[] columnNames;
    private String[] methodNames;
    private String[] setterMethodNames;
    /** Column classes, used for the TableModel method getColumnClass. */
    private Class[] cTypes;
    public DynamicTreeTableModel(TreeNode root, String[] columnNames,
                        String[] getterMethodNames,
                        String[] setterMethodNames,
                        Class[] cTypes) {
         super(root);
         this.columnNames = columnNames;
         this.methodNames = getterMethodNames;
         this.setterMethodNames = setterMethodNames;
         this.cTypes = cTypes;
    public int getChildCount(Object node) {
         return ((TreeNode)node).getChildCount();
    public Object getChild(Object node, int i) {
         return ((TreeNode)node).getChildAt(i);
    public boolean isLeaf(Object node) {
         return ((TreeNode)node).isLeaf();
    public int getColumnCount() {
         return columnNames.length;
    public String getColumnName(int column) {
         if (cTypes == null || column < 0 || column >= cTypes.length) {
         return null;
         return columnNames[column];
    public Class getColumnClass(int column) {
         if (cTypes == null || column < 0 || column >= cTypes.length) {
         return null;
         return cTypes[column];
    public Object getValueAt(Object node, int column) {
         try {
         Method method = node.getClass().getMethod(methodNames[column],
                                  null);
         if (method != null) {
              return method.invoke(node, null);
         catch (Throwable th) {}
         return null;
    * Returns true if there is a setter method name for column
    * <code>column</code>. This is set in the constructor.
    public boolean isCellEditable(Object node, int column) {
    return (setterMethodNames != null &&
         setterMethodNames[column] != null);
    // Note: This looks up the methods each time! This is rather inefficient;
    // it should really be changed to cache matching
    // methods/constructors
    // based on <code>node</code>'s class, and code>aValue</code>'s
    //class.
    public void setValueAt(Object aValue, Object node, int column) {
         boolean found = false;
         try {
         // We have to search through all the methods since the
         // types may not match up.
         Method[] methods = node.getClass().getMethods();
         for (int counter = methods.length - 1; counter >= 0; counter--) {
              if (methods[counter].getName().equals
              (setterMethodNames[column]) && methods[counter].
              getParameterTypes() != null && methods[counter].
              getParameterTypes().length == 1) {
              // We found a matching method
              Class param = methods[counter].getParameterTypes()[0];
              if (!param.isInstance(aValue)) {
                   // Yes, we can use the value passed in directly,
                   // no coercision is necessary!
                   if (aValue instanceof String &&
                   ((String)aValue).length() == 0) {
                   // Assume an empty string is null, this is
                   // probably bogus for here.
                   aValue = null;
                   else {
                   // Have to attempt some sort of coercision.
                   // See if the expected parameter type has
                   // a constructor that takes a String.
                   Constructor cs = param.getConstructor
                   (new Class[] { String.class });
                   if (cs != null) {
                        aValue = cs.newInstance(new Object[]
                                       { aValue });
                   else {
                        aValue = null;
              // null either means it was an empty string, or there
              // was no translation. Could potentially deal with these
              // differently.
              methods[counter].invoke(node, new Object[] { aValue });
              found = true;
              break;
         } catch (Throwable th) {
         System.out.println("exception: " + th);
         if (found) {
         // The value changed, fire an event to notify listeners.
         TreeNode parent = ((TreeNode)node).getParent();
         fireTreeNodesChanged(this, getPathToRoot(parent),
                        new int[] { getIndexOfChild(parent, node) },
                        new Object[] { node });
    public TreeNode[] getPathToRoot(TreeNode aNode) {
    return getPathToRoot(aNode, 0);
    private TreeNode[] getPathToRoot(TreeNode aNode, int depth) {
    TreeNode[] retNodes;
         // This method recurses, traversing towards the root in order
         // size the array. On the way back, it fills in the nodes,
         // starting from the root and working back to the original node.
    /* Check for null, in case someone passed in a null node, or
    they passed in an element that isn't rooted at root. */
    if(aNode == null) {
    if(depth == 0)
    return null;
    else
    retNodes = new TreeNode[depth];
    else {
    depth++;
    if(aNode == root)
    retNodes = new TreeNode[depth];
    else
    retNodes = getPathToRoot(aNode.getParent(), depth);
    retNodes[retNodes.length - depth] = aNode;
    return retNodes;
    // DynamicTreeTableModel.java END
    // IconRenderer.java BEGIN
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.plaf.basic.BasicTreeUI;
    class IconRenderer extends DefaultTreeCellRenderer
    // Color backColor = new Color(0xD0, 0xCC, 0xFF);
    Color backColor = new Color(0xF0, 0xF0, 0xE0);
    String tipText = "";
    JTree tree;
    int currRow = 0;
    boolean m_selected;
    JTable table;
    public IconRenderer(JTree tree, JTable table) {
    this.table = table;
    // setBackground(backColor);
    setBackground(Color.GREEN);
    setForeground(Color.black);
         this.tree = tree;
    public Component getTreeCellRendererComponent(JTree tree, Object value,
    boolean selected,
    boolean expanded, boolean leaf,
    int row, boolean hasFocus) {
         Object node = null;
         super.getTreeCellRendererComponent(
    tree, value, selected,
    expanded, leaf, row,
    hasFocus);
         TreePath treePath = tree.getPathForRow(row);
    if(treePath != null)
              node = treePath.getLastPathComponent();
    currRow = row;
    m_selected = selected;
    DefaultMutableTreeNode itc = null;
    if (node instanceof DefaultMutableTreeNode) {
    itc = (DefaultMutableTreeNode)node;
         setClosedIcon(closedIcon);
    setOpenIcon(openIcon);
    return this;
    /* Override the default to send back different strings for folders and leaves. */
    public String getToolTipText() {
    return tipText;
    * Paints the value. The background is filled based on selected.
    public void paint(Graphics g) {
         super.paint(g);
         Color bColor = null;
         if(!m_selected) {
              System.out.println(" iconren not sel currRow " + currRow);
              if(currRow % 2 == 0) {
                   bColor = Color.WHITE;
              } else {
              bColor = backColor;
         } else {
              bColor = table.getSelectionBackground();
              System.out.println("in else selbg = " + bColor);           
              bColor = new Color(0xF0, 0xCC, 0x92);
              System.out.println(" bColor aft = " + bColor);           
         int imageOffset = -1;
         if(bColor != null) {
         imageOffset = getLabelStart();
         g.setColor(bColor);
         if(!m_selected) {
              System.out.println(" not sel setting white ");
              g.setXORMode(new Color(0xFF, 0xFF, 0xFF));
         } else {
    //          g.setXORMode(new Color(0xCC, 0xCC, 0x9F));
              g.setXORMode(new Color(0x00, 0x00, 0x00));
              System.out.println(" using color = " + g.getColor());           
         if(getComponentOrientation().isLeftToRight()) {
         g.fillRect(imageOffset, 0, getWidth() - 1 - imageOffset,
                   getHeight());
         } else {
         g.fillRect(0, 0, getWidth() - 1 - imageOffset,
                   getHeight());
    private int getLabelStart() {
         Icon currentI = getIcon();
         if(currentI != null && getText() != null) {
         return currentI.getIconWidth() + Math.max(0, getIconTextGap() - 1);
         return 0;
    // IconRenderer.java END
    // IndicatorRenderer.java BEGIN
    // import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    import javax.swing.table.*;
    import javax.swing.table.*;
    import javax.swing.plaf.basic.*;
    import java.awt.event.*;
    import java.util.EventObject;
    import java.text.NumberFormat;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.StringTokenizer;
    import java.util.Arrays;
    class IndicatorRenderer extends DefaultTableCellRenderer {
    /** Makes sure the number of displayed in an internationalized
    * manner. */
    protected NumberFormat formatter;
    /** Row that is currently being painted. */
    protected int lastRow;
    protected int reloadRow;
    protected int reloadCounter;
    protected TreeTableModel treeTableModel;
    protected TreeTableModelAdapter treeTblAdapter;
    protected JTable table;
    Component renderer = null;
    Color backColor = new Color(0xF0, 0xF0, 0xE0);
    IndicatorRenderer(TreeTableModelAdapter treeTblAdapter, TreeTableModel treeTableModel) {
         setHorizontalAlignment(JLabel.RIGHT);
         setFont(new Font("serif", Font.BOLD, 12));
         this.treeTableModel = treeTableModel;
         this.treeTblAdapter = treeTblAdapter;
    * Invoked as part of DefaultTableCellRenderers implemention. Sets
    * the text of the label.
    public void setValue(Object value) {
    /* setText((value == null) ? "---" : formatter.format(value)); */
         setText((value == null) ? "---" : (String) value.toString());
    * Returns this.
    public Component getTableCellRendererComponent(JTable table,
    Object value, boolean isSelected, boolean hasFocus,
    int row, int column) {
         renderer = super.getTableCellRendererComponent(table, value, isSelected,
    hasFocus, row, column);
         lastRow = row;
         this.table = table;
              if(isSelected) {
                   doMask(hasFocus, isSelected);
              } else
              setBackground(table.getBackground());
    return renderer;
    * If the row being painted is also being reloaded this will draw
    * a little indicator.
    public void paint(Graphics g) {
         super.paint(g);
    private void doMask(boolean hasFocus, boolean selected) {
              maskBackground(hasFocus, selected);
    private void maskBackground(boolean hasFocus, boolean selected) {
              Color seed = null;
              seed = table.getSelectionBackground();
              Color color = seed;
              if (color != null) {
                   setBackground(
    new Color(0xF0, 0xCC, 0x92));
    // IndicatorRenderer.java END
    // JTreeTable.java BEGIN
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    import javax.swing.table.*;
    import java.awt.event.*;
    import java.util.EventObject;
    public class JTreeTable extends JTable {
    /** A subclass of JTree. */
    protected TreeTableCellRenderer tree;
    protected IndicatorRenderer indicatorRenderer = null;
    public JTreeTable(TreeTableModel treeTableModel) {
         super();
         // Creates the tree. It will be used as a renderer and editor.
         tree = new TreeTableCellRenderer(treeTableModel);
         TreeTableModelAdapter tdap = new TreeTableModelAdapter(treeTableModel, tree);
         // Installs a tableModel representing the visible rows in the tree.
         super.setModel(tdap);
         // Forces the JTable and JTree to share their row selection models.
         ListToTreeSelectionModelWrapper selectionWrapper = new
         ListToTreeSelectionModelWrapper();
         tree.setSelectionModel(selectionWrapper);
         setSelectionModel(selectionWrapper.getListSelectionModel());
         // Installs the tree editor renderer and editor.
         setDefaultRenderer(TreeTableModel.class, tree);
         setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
         indicatorRenderer = new IndicatorRenderer(tdap, treeTableModel);     
         // No grid.
         setShowGrid(false);
         // No intercell spacing
         setIntercellSpacing(new Dimension(0, 0));     
         // And update the height of the trees row to match that of
         // the table.
         //if (tree.getRowHeight() < 1) {
         // Metal looks better like this.
         setRowHeight(20);
    public TableCellRenderer getCellRenderer(int row, int col) {
              if(col == 0)
              return tree;
              else
              return indicatorRenderer;     
    public void updateUI() {
         super.updateUI();
         if(tree != null) {
         tree.updateUI();
         // Do this so that the editor is referencing the current renderer
         // from the tree. The renderer can potentially change each time
         // laf changes.
         setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
         // Use the tree's default foreground and background colors in the
         // table.
    LookAndFeel.installColorsAndFont(this, "Tree.background",
    "Tree.foreground", "Tree.font");
    public int getEditingRow() {
    return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 :
         editingRow;
    private int realEditingRow() {
         return editingRow;
    public void sizeColumnsToFit(int resizingColumn) {
         super.sizeColumnsToFit(resizingColumn);
         if (getEditingColumn() != -1 && getColumnClass(editingColumn) ==
         TreeTableModel.class) {
         Rectangle cellRect = getCellRect(realEditingRow(),
                             getEditingColumn(), false);
    Component component = getEditorComponent();
         component.setBounds(cellRect);
    component.validate();
    public void setRowHeight(int rowHeight) {
    super.setRowHeight(rowHeight);
         if (tree != null && tree.getRowHeight() != rowHeight) {
    tree.setRowHeight(getRowHeight());
    public JTree getTree() {
         return tree;
    public boolean editCellAt(int row, int column, EventObject e){
         boolean retValue = super.editCellAt(row, column, e);
         if (retValue && getColumnClass(column) == TreeTableModel.class) {
         repaint(getCellRect(row, column, false));
         return retValue;
    public class TreeTableCellRenderer extends JTree implements
         TableCellRenderer {
         /** Last table/tree row asked to renderer. */
         protected int visibleRow;
         /** Border to draw around the tree, if this is non-null, it will
         * be painted. */
         protected Border highlightBorder;
         public TreeTableCellRenderer(Tr

  • Using JTreeTable as a Bean

    Hi,
    I've been looking at the JTreeTable class available at:
    http://java.sun.com/products/jfc/tsc/articles/treetable1/
    This is not a standard Swing component but I'd like to use it as a Bean so that I can load it into my NetBeans IDE. Problem is there does not appear to be a means to set the model (for tree and table) other than using the constructor that takes a TreeTableModel parameter.
    Has this been done before? Any help is appreciated.
    Thanks,
    Derek.

    Mabe you also should rewrite the other constructor:
    public JTreeTable(TreeTableModel treeTableModel) {
         super();
            setTreeTableModel(treeTableModel);
            // Installs the tree editor.
            setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
         // No grid.
         setShowGrid(false);
         // No intercell spacing
         setIntercellSpacing(new Dimension(0, 0));     
    public void setTreeTableModel(TreeTableModel treeTableModel){
         // Creates the tree. It will be used as a renderer and editor.
         tree = new TreeTableCellRenderer(treeTableModel);
         // Installs a tableModel representing the visible rows in the tree.
         super.setModel(new TreeTableModelAdapter(treeTableModel, tree));
         // Forces the JTable and JTree to share their row selection models.
         ListToTreeSelectionModelWrapper selectionWrapper = new
                                 ListToTreeSelectionModelWrapper();
         tree.setSelectionModel(selectionWrapper);
         setSelectionModel(selectionWrapper.getListSelectionModel());
         // Installs the tree renderer
         setDefaultRenderer(TreeTableModel.class, tree);
         // And update the height of the trees row to match that of
         // the table.
         if (tree.getRowHeight() < 1) {
             // Metal looks better like this.
             setRowHeight(20);
        public TreeTableModel getTreeTableModel(){
          return getModel();
        }Something like this. Didn't test it!
    -Puce

  • Custom Renderers in JTreeTable (or extending JTable)?

    I am wondering about what the best approach is to display a table in a Swing component. My table will by default have all rows collapsed (occupying a single line), but someone may click on a row to expand it (so it occupies multiple lines and displays more information). Nothing in the table should be editable.
    Example:
    (collapsed) 1. data     data     data
    (expanded) 2. data     data     data
    ...more data that wouldn't fit on on one line...
    ... still more data (additional data doesn't have same column format as collapsed rows)...
    (collapsed) 3. data     data     dataSo the additional data displayed when a row is expanded aren't conceptually `children' of the data in the collapsed display. I've looked at JTreeTable, but I'm not sure it's right for this purpose, and it seems complicated.
    For one thing, I need some of my columns to have custom renderers--for example, renderers that display a button with text or an image instead of just a label. However, it looks like the JTreeTable approach forces you to declare the JTree (extension) as the renderer of everything in a row, so would that prevent me from specifying custom renderers for other columns, or am I misunderstanding?
    Another feature I need is to be able to filter out entire rows from the view (so they don't show up at all). I will also want to add custom sort buttons that can apply four different sorts to each column.
    Would I be better off using a JTreeTable for this or somehow using custom renderers or otherwise extending an ordinary JTable to make the column larger and display additional information when the user clicks the expand icon?
    Also, how do I specify a different renderer for header rows than for other rows?
    Message was edited by:
    The.Joy.of.Java

    Check how editingStopped is being done. For a ComboBox there is no common operation that one can assume means that the user is done with the editing component. By default JTable leaves it active until the mouse clicks somewhere outside it, then does, essentially, fireEditingStopped() to give the cell back to the renderer. Then a second mouse click is required to start a new cell editor.
    If you're using ComboBox as a custom editor, you have to decide what event you want to be final and call fireEditingStopped() yourself. For instance, in your TableCellEditor:
        @Override
        public Component getTableCellEditorComponent(final JTable table,
                                                     final Object value,
                                                     final boolean isSelected,
                                                     final int row,
                                                     final int column) {
    ...             if( editor.supportsCustomEditor() )  {
                        JComboBox c = (JComboBox)editor.getCustomEditor();
                        c.removeActionListener( this );
                        c.addActionListener( this );
                        return c;
        @Override
        public void actionPerformed ( final ActionEvent ev ) {
            else if( "comboBoxChanged".equals( ev.getActionCommand() ) )  {
                fireEditingStopped();
        }The actionEvent is fired when just about anything happens in the ComboBox, including selection of the currently selected item. But unless you have a more specific requirement, it should be good enough.

  • Multiple DnD in JTreeTable

    Hi Folks--
    two weeks ago I started to implement Drag and Drop for my wonderful TreeTableComponent, that is based on a JTreeTable described in an article by sun. It didn't took me long to figure that dnd is not the easiest thing to do for a JTreeTable. So I browsed this forum and found many other people who have or had the same problem. Since the given answers didn't help me so much, I thought it would be good to publish my implementation here:
    After two weeks I managed to implement dnd in the right way (as I belive). Here's my solution.
    1. disable internal dnd function by setDragEnabled(false)
    2. set your own transfer handler that manages dnd for you (derive from TransferHander or simply create an instance of TransferHandler)
    3. add a mouse listener and a mouse motion listener to your treeTable to tell the transfer handler to start the drag
    4. revert order of mouse listener that you mouse listener is called first -> this is importent to keep selection on all previously selected nodes (prevents internal mouse handler of tree changing selection to the node you just clicked onto)
    5. set selection mode of table and tree to make multiple selection possible to the user
    add this where you init the table:
    ('table' is instance of a JTreeTable derivative)
            //disable internal dnd functionality, because we need our own implementation
            table.setDragEnabled(false); 
           //attach transfer handler
            table.setTransferHandler(createTransferHandler());
            //since we have a transfer handler, we just need to attach mouse listeners
            //to initiate the drag inside of the transfer handler
            DnDMouseAdapter dndMouseAdapter = new DnDMouseAdapter();
            table.addMouseListener(dndMouseAdapter);
            table.addMouseMotionListener(new DnDMouseMotionAdapter());
            //revert MouseListeners order so that our MouseListener is called first
            //this is important to give drag n drop first priority and prevent the
            //internal mouse handler of tableUI changing the selection.
            MouseListener[] mls = table.getMouseListeners();
            for (int i = 0; i < mls.length; i++) {
                if (mls[i] != dndMouseAdapter) {
                    table.removeMouseListener(mls);
    table.addMouseListener(mls[i]);
    //set multiple selection
    table.getSelectionModel().setSelectionMode(getSelectionMode());
    //set selection mode for tree
    final JTree tree = getTreeTable().getTree();
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
    The idea for the mouse listeners I got from sun's swing tutorial. So here's the code for dndMouseAdapter and dndMouseMotionAdapter:
      class DnDMouseAdapter extends MouseAdapter {
            public void mousePressed(MouseEvent e) {
                firstMouseEvent = e;
                e.consume();
            public void mouseReleased(MouseEvent e) {
                firstMouseEvent = null;
        class DnDMouseMotionAdapter extends MouseMotionAdapter {
            //define diplacement of five pixel for as drag
            private static final int PIXEL_DISPLACEMENT = 5;
            public void mouseDragged(MouseEvent e) {
                if (firstMouseEvent != null) {
                    e.consume();
                    //if the user holds down the control key -> COPY, otherwise MOVE
                    int ctrlMask = InputEvent.CTRL_DOWN_MASK;
                    int action = ((e.getModifiersEx() & ctrlMask) == ctrlMask) ? TransferHandler.COPY : TransferHandler.MOVE;
                    int dx = Math.abs(e.getX() - firstMouseEvent.getX());
                    int dy = Math.abs(e.getY() - firstMouseEvent.getY());
                    //define a displacement of at least some pixel as a drag
                    if (dx > DnDMouseMotionAdapter.PIXEL_DISPLACEMENT || dy > DnDMouseMotionAdapter.PIXEL_DISPLACEMENT) {
                        //starting to drag...
                        JComponent c = (JComponent) e.getSource();
                        TransferHandler handler = c.getTransferHandler();
                        //tell transfer handler to start drag
                        handler.exportAsDrag(c, firstMouseEvent, action);
                        //reset first mouse event for the next time
                        firstMouseEvent = null;
        }I hope that helps! ;-)
    Any comment is apprechiated!
    Kind regards,
    Patrick

    I'm absolutetly devastated!!
    I spent hours looking for advice on a treetable component after someone mentioned the idea not too long ago, in another thread might I add.
    And I just spent the last 2 damn weeks implementing myy own. I feel heart broken! JTreeTable v1 was even very similar tomy first bash...but I gave on using the JTree as the renderer as it just looked lame... the way I did it anyway.
    So just today I finished my own impl, with a new JComponent derivative soley for the rendering of the tree-like column.
    Any clue as to when they intend to make it a standard JFC Swing component.
    Bloody marvelous! So annoyed as it was a serious road-block to my current project! And asmuch as it was fun, I didn't choose to do for fun. AAAAAAARRRGGH!!
    ps. congratulations, if you feel at all like how I felt half an hour ago, you must be very chuffed.

  • Where to consume expansion click in JTreeTable?

    Hi!
    I have the following question concerning a JTreeTable (tried it with the classic TreeTableExample2 from http://java.sun.com/products/jfc/tsc/articles/treetable2/index.html ) :
    I want that whenever I click an expand/collapse button of the Tree either the JTable does not change the selection or it does not call my ListSelectionListeners. Where do I have to consume the mouse event on the button so that the JTable does not react? is it possible at all?
    thanks,
    Nils

    To install javascripts in Bridge go to the app preferences and select startup scripts from the list…
    You will then see a button if you click that your folder is revealed… Just pop them in that and restart the app…
    You may be prompted to add new at restart of the app…

  • JComboBox in JTreeTable

    One column in my JTreeTable (or JTable, doesn't matter) is a JComboBox. If it's a Checkbox the cell must be a "Boolean" and it's selected automatically if it's true. If I have a JLabel of JTextField the cell must be a String.
    But how do I set the selectedIndex of the ComboBox from my DataTable? For Instance:
    The ComboxBox has the items: "Michael", "Peter" and "Paul". The Cell is a String and is "Peter".
    What do I have to do in my ColumnModel that the ComboxBox for that cell shows "Peter". For all rows is always the first item visible.
    Thank you
    Jonas

    hi
    this is one link u can refer
    http://www.codeguru.com/java/articles/185.shtml
    http://www.devx.com/premier/mgznarch/javapro/2001/01jan01/vc0101/vc0101.asp
    i have tried first link that works fine
    Hope this helped u
    Renjith

  • JtreeTable - Nodes update issue - Nodes are cut off

    Hi,
    I'vet got a little problem with the JtreeTable. Everything works fine until I try to change the rendering of a row to BOLD.
    The text turns bold, but the TreeNode (first col in row) is cut off because it was first rendered plain and now its to big to be
    displayed.
    I tried
    tree.getModel().valueForPathChanged(new TreePath(node.getPath()), myNewValue);but beacuse value doesn't change (text stays just font changes) there is no need to fireNodesChanged.

    Here's one I put together. Select any node, and any other node with text that begins with the same letter is rendered in bold. From my test, it looks like repaint on the tree isn't sufficient. However, firing node changed events seem to be working (as a quick and dirty measure, I fire node changed on every node each time). Now I have to go back and revisit the problem I originally had and see what I was doing there.
    import java.awt.BorderLayout;
    import java.awt.FlowLayout;
    import javax.swing.*;
    import javax.swing.event.TreeSelectionEvent;
    import javax.swing.event.TreeSelectionListener;
    import javax.swing.tree.*;
    public class BoldTreeCellTest {
         public static void main(String[] args) {
              SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
                        launchUI();
         private static void launchUI() {
              final DefaultMutableTreeNode[] nodes = new DefaultMutableTreeNode[5];
              JFrame frame = new JFrame("Test JTree With Bold Rendering");
              nodes[0] = new DefaultMutableTreeNode("root of the tree here");
              nodes[1] = new DefaultMutableTreeNode("Every cell which has the");
              nodes[2] = new DefaultMutableTreeNode("same first character as the");
              nodes[3] = new DefaultMutableTreeNode("selected cell text will have it's text");
              nodes[4] = new DefaultMutableTreeNode("rendered in bold.");
              for (int i=1; i<nodes.length; i++) {
                   nodes[0].add(nodes);
              final DefaultTreeModel model = new DefaultTreeModel(nodes[0]);
              final JTree tree = new JTree(model);
              final JRadioButton useRepaintButton = new JRadioButton("Repaint Tree", true);
              final JRadioButton useNodesChangedButton = new JRadioButton("Fire Nodes Changed");
              ButtonGroup buttonGroup = new ButtonGroup();
              buttonGroup.add(useRepaintButton);
              buttonGroup.add(useNodesChangedButton);
              tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
                   @Override
                   public void valueChanged(TreeSelectionEvent event) {
                        if (useRepaintButton.isSelected()) {
                             tree.repaint();
                        } else {
                             model.nodeChanged(nodes[0]);
                             model.nodesChanged(nodes[0], new int[] {0, 1, 2, 3});
              tree.setCellRenderer(new BoldTreeCellRenderer());
              JScrollPane pane = new JScrollPane(tree);
              JPanel panel = new JPanel(new BorderLayout());
              JPanel buttonPanel = new JPanel(new FlowLayout());
              buttonPanel.add(useRepaintButton);
              buttonPanel.add(useNodesChangedButton);
              panel.add(buttonPanel, BorderLayout.NORTH);
              panel.add(pane, BorderLayout.CENTER);
              frame.setContentPane(panel);
              frame.pack();
              frame.setLocationRelativeTo(null);
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setVisible(true);
    import java.awt.Component;
    import java.awt.Font;
    import javax.swing.JLabel;
    import javax.swing.JTree;
    import javax.swing.tree.DefaultMutableTreeNode;
    import javax.swing.tree.DefaultTreeCellRenderer;
    import javax.swing.tree.TreePath;
    public class BoldTreeCellRenderer extends DefaultTreeCellRenderer {
         private Font plainFont;
         private Font boldFont;
         public BoldTreeCellRenderer() {
              super();
              Font baseFont = (new JLabel()).getFont();
              this.plainFont = baseFont.deriveFont(Font.PLAIN);
              this.boldFont = baseFont.deriveFont(Font.BOLD);
         @Override
         public Component getTreeCellRendererComponent(JTree tree, Object value,
                   boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
              super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
              String st = (String) ((DefaultMutableTreeNode) value).getUserObject();
              Font font = this.plainFont;
              TreePath selectionPath = tree.getSelectionPath();
              if (selectionPath != null) {
                   String selectedText = (String) ((DefaultMutableTreeNode) selectionPath.getLastPathComponent()).getUserObject();
                   if (st.startsWith(selectedText.substring(0, 1))) {
                        font = this.boldFont;
              setFont(font);
              return this;
    Edited by: Skotty on Aug 12, 2010 2:02 PM
    Edited by: Skotty on Aug 12, 2010 2:05 PM - set useRepaintButton as selected on start                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

  • Editing non-tree cells problem in JTreeTable

    Hello all,
    I've been playing around with the JTreeTable for quite a while and have a fairly good grip on it. However, I've run into a problem that involves the display of cell data in the non-tree cells.
    Assume I have a JTreeTable with one node below the root (and the root node is not displayed). Also assume I've edited some information in one of the other cells in a 5-celled JTreeTable. The JTreeTable behaves normally with regard to editing/setting the values of the table cells.
    Now, with the click of a separate button, I programmatically create a new node in the JTree. I update the JTree model with a call to nodeChanged() and nodeStructureChanged() (or I could call reload() - both seem to work).
    This successfully adds a node, but in the process clears the entire remainder of the table's cell values. If I call fireTableDataChanged(), then the display of the JTree gets all screwed up (basically what happens to the display if you add/remove nodes, but don't update the display in a JTree). Not only that, but the fireTableDataChanged() method still does not redisplay my cell information for the remainder of the table.
    I'm at a loss to figure out what's responsible for this. The tableCellRenderer seems to work just fine until I add node. Even then, the tableCellRenderer for the JTree still works until I call fireTableDataChanged().
    Any ideas?
    Thank you,
    Brion Swanson

    I use a JTreeTable and in looking at my code, I've
    noticed that I make use of treeTable.repaint() fairly
    frequently (as whenever I update my stuff).Did the treeTable.updateUI do funky things to your JTree? It does on mine if I do a programmatic node addition or removal (basically any change to the tree structure will cause treeTable.updateUI() to completely destroy the display of the tree). This is a separate issue, but I thought I'd ask anyway since you seem to have run into at least a few of the same problems I'm experiencing.
    I don't fully understand your problem<snip/>
    do you mean
    it drops all edits you have done?Yes, it drops all the edits except the one currently being "edited" (that is, the selected editable cell will not lose it's value).
    I had a problem about it dropping the edits I had
    done and I resolved them by adding key listeners
    and played with the TableCellEditor.Could you elaborate on what you did to the TableCellEditor and which object you had listening to the keys (the table? or the tree? or something else?).
    You help is greatly appreciated!
    Brion Swanson

  • JTreeTable / TreeModel question

    Hi all,
    I have two questions about JTrees and TreeModels.
    I have an application which builds a TreeModel from an XML file, and displays it in a JTreeTable (see: http://java.sun.com/products/jfc/tsc/articles/treetable1/). There are two panels to display an XML file. The XML file consists of parameters which all have a name and a value:
    root
    |- header
    |  |- parameter1                value
    |  |- parameter2                value
    |  |- parameter3                value
    |- data
       |- parameter1                value
       |   |- parameter1.1          value
       |   |- parameter1.2          value
       |- parameter2                value
       |   |- parameter2.1          value
       |- parameter3                value
       |- parameter4                valueNow I want to compare two nodes (one from both panels). The user can select a node on both panels to compare.
    There are two tasks I want to implement:
    1) I want to compare the parameters without taking into account the order in which they appear. A parameter is considered different when it has the same parent, the same name, but a different value.
    2) I also want to separate those parameters which are unique for both trees (it doesn't appear in the other tree)
    Thus, if I want to compare a node from jtree1, I first need to find a corresponding node in jtree2. If I can't find it, it is unique in jtree1, else I can compare the values and decide if they are the same. But how can I check for the corresponding node in jtree2?
    There is also a second problem, how can I get the selected node from a JTreeTable? I tried with getSelectedIndex(), but when parameter1.1 is selected, the getSelectedIndex returns 7, while the root lement only has two child nodes... so getChildAt(index) will not work.

    You can accomplish what you are looking to do through the use of something called model filtering. I have published an article on it on IBM's website at http://www-106.ibm.com/developerworks/library/j-filters/?dwzone=java.
    I would direct you to the part that discusses 'exclusion filters' in particular. If you want to adapt this to the TreeModel architecture, it should be fairly simple.
    Mitch Goldstein
    Author, Hardcore JFC (Cambridge Univ Press)
    [email protected]

  • Different tooltips in JTreeTable

    Hi all!
    I have a JTreeTable (the rows are the nodes of a tree), very similar to the one at
    http://java.sun.com/products/jfc/tsc/articles/treetable2/
    I'd like to add different ToolTips in every node (in the example in the sun's site, for example see as a tooltip the file's name). How can I do that? Should I do that in the cell render method? Has anybody any example about that?
    Feedbacks are really appreciated!
    Thanks
    Franky

    Sure, sorry for the mistake about the tags...Follows the class I use to render the JTreeTable. My doubt is that I have to do something with the mouse listener to active the tooltip, could it be?
    Thanks
    public class TreeTableCellRenderer
              extends JTree
              implements TableCellRenderer {
              protected int visibleRow;
              protected Border highlightBorder;
              public TreeTableCellRenderer(TreeModel model) {
                   super(model);
              public void updateUI() {
                   super.updateUI();
                   // Make the tree's cell renderer use the table's cell selection
                   // colors.
                   TreeCellRenderer tcr = getCellRenderer();
                   if (tcr instanceof DefaultTreeCellRenderer) {
                        DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer) tcr);
                        // For 1.1 uncomment this, 1.2 has a bug that will cause an
                        // exception to be thrown if the border selection color is
                        // null.
                        // dtcr.setBorderSelectionColor(null);
                        dtcr.setTextSelectionColor(
                             UIManager.getColor("Table.selectionForeground"));
                        dtcr.setBackgroundSelectionColor(
                             UIManager.getColor("Table.selectionBackground"));
              public void setRowHeight(int rowHeight) {
                   if (rowHeight > 0) {
                        super.setRowHeight(rowHeight);
                        if (JSortTreeTable.this != null
                             && JSortTreeTable.this.getRowHeight() != rowHeight) {
                             JSortTreeTable.this.setRowHeight(getRowHeight());
              public void setBounds(int x, int y, int w, int h) {
                   super.setBounds(x, 0, w, JSortTreeTable.this.getHeight());
              public void paint(Graphics g) {
                   g.translate(0, -visibleRow * getRowHeight());
                   super.paint(g);
                   // Draw the Table border if we have focus.
                   if (highlightBorder != null) {
                        highlightBorder.paintBorder(
                             this,
                             g,
                             0,
                             visibleRow * getRowHeight(),
                             getWidth(),
                             getRowHeight());
               * TreeCellRenderer method. Overridden to update the visible row.
              public Component getTableCellRendererComponent(
                   JTable table,
                   Object value,
                   boolean isSelected,
                   boolean hasFocus,
                   int row,
                   int column) {
                   Color background;
                   Color foreground;
                   this.setToolTipText("Tooltip");
                   System.out.println("Tooltip "+this.getToolTipText());
                   if (isSelected) {
                        background = table.getSelectionBackground();
                        foreground = table.getSelectionForeground();
                   } else {
                        background = table.getBackground();
                        foreground = table.getForeground();
                   highlightBorder = null;
                   if (realEditingRow() == row && getEditingColumn() == column) {
                        background = UIManager.getColor("Table.focusCellBackground");
                        foreground = UIManager.getColor("Table.focusCellForeground");
                   visibleRow = row;
                   setBackground(background);
                   TreeCellRenderer tcr = getCellRenderer();
                   if (tcr instanceof DefaultTreeCellRenderer) {
                        DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer) tcr);
                        if (isSelected) {
                             dtcr.setTextSelectionColor(foreground);
                             dtcr.setTextNonSelectionColor(foreground);
                             dtcr.setBackgroundSelectionColor(background);
                        } else {
                             dtcr.setTextNonSelectionColor(foreground);
                             dtcr.setBackgroundNonSelectionColor(background);
                        Icon tutorialIcon;
                        ImageIcon icon3= new ImageIcon("C:\\eclipse\\workspace\\Java\\itemrevision.gif");
                        tutorialIcon=icon3;
                        dtcr.setOpenIcon((Icon) tutorialIcon);
                        dtcr.setClosedIcon((Icon) tutorialIcon);
                        dtcr.setLeafIcon((Icon) tutorialIcon);
                   return this;
         }

Maybe you are looking for