Extra Row in JTree

J

Jason Cavett

I'm having an issue when adding a new node to a JTree. Here's the
code in question:

this.setEditable(true);

if (parent == null) {
treeModel.insertNodeInto(child, rootNode, rootNode.getChildCount());
} else {
treeModel.insertNodeInto(child, parent, parent.getChildCount());
}

this.setEditable(false);

I then call "expandPath(e.getTreePath())" inside the TreeModelListener
that I have added to treeModel (which is my own DefaultTreeModel).
Unfortunately, when I do this expandPath, there appears to be an extra
row in the tree. Something like this:

Root
- Item1
- Item2
[BLANK ROW]
- Item3

From the research I did, it appears to be a problem with the
userObject (based on this discussion:
http://www.javakb.com/Uwe/Forum.aspx/java-gui/6527/JTree-display-update-issue-with-new-nodes),
but I'm really having a problem fixing it. I definitely need the
expandPath to happen, so I'm not sure what else to do.

Anybody have any suggestions on fixing this?

Thanks!
 
J

Jason Cavett

I'm having an issue when adding a new node to a JTree.  Here's the
code in question:

this.setEditable(true);

if (parent == null) {
  treeModel.insertNodeInto(child, rootNode, rootNode.getChildCount());} else {

  treeModel.insertNodeInto(child, parent, parent.getChildCount());

}

this.setEditable(false);

I then call "expandPath(e.getTreePath())" inside the TreeModelListener
that I have added to treeModel (which is my own DefaultTreeModel).
Unfortunately, when I do this expandPath, there appears to be an extra
row in the tree.  Something like this:

Root
  - Item1
    -  Item2
[BLANK ROW]
  - Item3

From the research I did, it appears to be a problem with the
userObject (based on this discussion:http://www.javakb.com/Uwe/Forum.aspx/java-gui/6527/JTree-display-upda...),
but I'm really having a problem fixing it.  I definitely need the
expandPath to happen, so I'm not sure what else to do.

Anybody have any suggestions on fixing this?

Thanks!

Alright, I'm replying to myself because I figured out a solution, but
I still don't understand what is happening, and I'd like to know.

My solution was, in the TreeModelListener.treeNodesInserted
(TreeModelEvent), do this:

// Expand the path to the node and scroll to the node.
if (e.getTreePath() != null) {
final TreeModelEvent event = e;
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
PropertiesTree.this.expandPath(event.getTreePath());
PropertiesTree.this.scrollPathToVisible(event.getTreePath());
}
});
}

It appears that I have to wait for the insertion to finish or
something, but I really don't understand why this is working. Can
anybody explain?

Thank you.
 
J

John B. Matthews

[...]
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PropertiesTree.this.expandPath(event.getTreePath());
PropertiesTree.this.scrollPathToVisible(event.getTreePath());
}
}); [...]

It appears that I have to wait for the insertion to finish or
something, but I really don't understand why this is working. Can
anybody explain?

Without seeing your <http://pscode.org/sscce.html>, I am uncertain. If
modifying the GUI on the EDT fixes the problem, you should verify that
you are building the GUI on the EDT:

<http://java.sun.com/docs/books/tutorial/uiswing/concurrency/initial.html>
 
J

Jason Cavett

[...]
  SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
      PropertiesTree.this.expandPath(event.getTreePath());
      PropertiesTree.this.scrollPathToVisible(event.getTreePath());
    }
  }); [...]

It appears that I have to wait for the insertion to finish or
something, but I really don't understand why this is working.  Can
anybody explain?

Without seeing your <http://pscode.org/sscce.html>, I am uncertain. If
modifying the GUI on the EDT fixes the problem, you should verify that
you are building the GUI on the EDT:

<http://java.sun.com/docs/books/tutorial/uiswing/concurrency/initial.html>

Unfortunately, coding an SSCCE isn't really feasible. The problem
doesn't occur when I'm working within an SSCCE, so I'm guessing it's
something in the architecture.

Anyway, I did read the link you provided, but I am scheduling the
opening of the view on the EDT. In fact, I do it via an invokeLater
call originally. (User clicks on a button, button opens the view on
EDT through a SwingUtilities.invokeLater(Runnable) call.)

From what I can tell everything seems right. Other people have had
this problem as well after I did a bit of searching online. But,
nobody seems to have a real solid solution. A problem with the JTree
perhaps?

Anyway, thanks for the info. Again, wish I could do the SSCCE, but I
can't get the problem to repeat there.
 
J

John B. Matthews

Jason Cavett said:
Unfortunately, coding an SSCCE isn't really feasible. The problem
doesn't occur when I'm working within an SSCCE, so I'm guessing it's
something in the architecture.

Anyway, I did read the link you provided, but I am scheduling the
opening of the view on the EDT. In fact, I do it via an invokeLater
call originally. (User clicks on a button, button opens the view on
EDT through a SwingUtilities.invokeLater(Runnable) call.)

AFAIK, there is only one EDT in a given VM. Isn't the button itself
constructed on the EDT?
From what I can tell everything seems right. Other people have had
this problem as well after I did a bit of searching online. But,
nobody seems to have a real solid solution. A problem with the JTree
perhaps?

Bugs notwithstanding, a known problem with JTree and most Swing
components is that they are not thread safe.
Anyway, thanks for the info. Again, wish I could do the SSCCE, but I
can't get the problem to repeat there.

Is it possible that your model is being modified in a different thread?
 
J

Jason Cavett

AFAIK, there is only one EDT in a given VM. Isn't the button itself
constructed on the EDT?


Bugs notwithstanding, a known problem with JTree and most Swing
components is that they are not thread safe.


Is it possible that your model is being modified in a different thread?

No to none of the above. I'm just initializing everything on the EDT
(and, yes, there's only one EDT). It appears that the JTree wants me
to wait until it's completely created before doing the expansion on
the tree.

Ah well. One of those mysterious "Swing things."
 
J

John B. Matthews

[...]
No to none of the above. I'm just initializing everything on the EDT
(and, yes, there's only one EDT). It appears that the JTree wants me
to wait until it's completely created before doing the expansion on
the tree.

That makes sense. SwingUtilities.invokeLater() has the salutary effect
of deferring action until all pending events have been processed.
Ah well. One of those mysterious "Swing things."

I belabor the point because so many Swing "mysteries" are revealed to be
threading misadventures. This is particularly easy when the model and
view execute in different threads.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

[SWING] Problem with JTree 2
JTable within JTree 1
JTree navigation 1
JTree problem 0
Jtree renderers 0
DOM extension of JTree 2
How to Get Root Path in JTree 2
How to use JTree with very large data? 6

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top