I have a problem when refreshing a JTree instance. See the following code:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class ItemTest {
private JFrame frame;
private DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
private JTree tree = new JTree(root);
private JButton button = new JButton("Rebuild");
private String[] array = new String[] { "name", "first_name", "middle_name", "last_name"};
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
ItemTest window = new ItemTest();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public ItemTest() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 523, 349);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane scrollBar = new JScrollPane();
GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
groupLayout.setHorizontalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGroup(groupLayout.createSequentialGroup()
.addContainerGap()
.addComponent(scrollBar, GroupLayout.PREFERRED_SIZE, 200, GroupLayout.PREFERRED_SIZE)
.addComponent(button, GroupLayout.PREFERRED_SIZE, 85, GroupLayout.PREFERRED_SIZE)
.addContainerGap(412, Short.MAX_VALUE))
);
groupLayout.setVerticalGroup(
groupLayout.createParallelGroup(Alignment.LEADING)
.addGroup(groupLayout.createSequentialGroup()
.addGap(22)
.addComponent(scrollBar, GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)
.addComponent(button, GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE)
.addContainerGap())
);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
root.add(new DefaultMutableTreeNode("Row 4"));
((DefaultTreeModel) tree.getModel()).nodeChanged(root);
}
});
for(String string : array) {
root.add(new DefaultMutableTreeNode(string));
}
scrollBar.setViewportView(tree);
frame.getContentPane().setLayout(groupLayout);
}
}
If we run this code, and expand the "Root" node. We will see 4 nodes in it. If we click the button "Rebuild", the tree won't update it's self. The weird thing is, if we don't expand the "Root" node at the begin (so just start the application) and click the button, and after that we expand the "Root" node, the new row is added. Does anyone knows how to refresh this tree without collapsing, because nodeChanged doesn't seem to work when you expand the "Root" node at the begin.
Note: I have to accomplish this without using insertNodeInto.
You must notify the listeners that a node was inserted:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
root.add(new DefaultMutableTreeNode("Row 4"));
((DefaultTreeModel) tree.getModel()).nodesWereInserted(
root, new int[]{root.getChildCount()-1});
}
});