JDK-4393970 : Inconsistent behavior in DefaultTreeModel.nodesWereInserted()
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2000-11-30
  • Updated: 2000-12-19
  • Resolved: 2000-12-19
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.0 betaFixed
Related Reports
Relates :  
Description

Name: yyT116575			Date: 11/30/2000



Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

When a JTree is created with a DefaultTreeModel you can programmatically add
DefaultMutableTreeNodes and fire the appropriate events by calling
DefaultTreeModel.nodesWereInserted().  In some cases, the JTree does not update
appropriately.  In particular, when the parent node has no children it appears
to fail.

>1.Exact steps to reproduce the problem.

Run the test program below.  Clicking 'add' adds a single node at index 0 below
the root, and calls nodesWereInserted appropriately.  Clicking 'delete' removes
a node from index 0 (if one exists) and calls nodesWereRemoved.  Clicking
'refresh' calls nodeStructureChanged on the root node.

Click 'add' three or four times to add new nodes to the root node.  Note that
the root node icon changes to indicate that children are present, but no
children are visible.  Now click refresh--there's the children!  Now click add
and delete a few times to see that the child nodes are properly appearing and
disappearing.

Delete all of the children by pressing 'delete' until they're all gone.  Now hit
'add'.  Note that this time a child node appears.  Remove all the children again
and hit 'refresh'.  Now hitting add fails to display the children, although the
icon change again indicates they are there--just like when the tree was created.

End result:  sometimes nodesWereInserted() properly updates the JTree, sometimes
it doesn't.

>2.Java SOURCE CODE that demonstrates the problem, if possible.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;

public class TestTree extends JFrame {
	protected JTree tree = null;
	protected DefaultMutableTreeNode rootNode = null;
	protected DefaultTreeModel model = null;

	public TestTree() {
		JPanel _panel = new JPanel(new BorderLayout());

		rootNode = new DefaultMutableTreeNode("Root");
		tree = new JTree(rootNode);
		model = (DefaultTreeModel)tree.getModel();

		_panel.add(new JScrollPane(tree), BorderLayout.CENTER);
		JPanel  _buttonPanel = new JPanel();
		JButton _button = new JButton("Add");
		_button.addActionListener(new HandleAdd());
		_buttonPanel.add(_button);

		_button = new JButton("Delete");
		_button.addActionListener(new HandleDelete());
		_buttonPanel.add(_button);

		_button = new JButton("Refresh");
		_button.addActionListener(new HandleRefresh());
		_buttonPanel.add(_button);
		_panel.add(_buttonPanel, BorderLayout.SOUTH);

		getContentPane().add(_panel);
		setSize(400, 400);
	}

	protected class HandleAdd implements ActionListener {
		public void actionPerformed(ActionEvent pAE) {
			int[] _iIndices = new int[1];
			DefaultMutableTreeNode _node = new DefaultMutableTreeNode("Add");
			rootNode.insert(_node, 0);
			_iIndices[0] = 0;
			model.nodesWereInserted(rootNode, _iIndices);
		}
	}

	protected class HandleDelete implements ActionListener {
		public void actionPerformed(ActionEvent pAE) {
			if (rootNode.getChildCount() < 1) return;
			DefaultMutableTreeNode _nodeChild = (DefaultMutableTreeNode)rootNode.getChildAt(0);
			int _iIndices[] = new int[1];
			_iIndices[0] = 0;
			rootNode.remove(_nodeChild);
			Object _objObjects[] = new Object[1];
			_objObjects[0] = _nodeChild;
			model.nodesWereRemoved(rootNode, _iIndices, _objObjects);
		}
	}

	protected class HandleRefresh implements ActionListener {
		public void actionPerformed(ActionEvent pAE) {
			model.nodeStructureChanged(rootNode);
		}
	}

	public static void main(String[] pArgs) {
		TestTree _tt = new TestTree();
		_tt.setVisible(true);
	}
}

(Review ID: 111631) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta FIXED IN: merlin-beta INTEGRATED IN: merlin-beta
14-06-2004

WORK AROUND Before a node is removed that will cause the node to no longer be a leaf, invoke collapsePath, then remove the node. scott.violet@eng 2000-12-04
04-12-2000

EVALUATION JTree maintains the expanded state of the nodes, this allows for the state to be preserved across look and feel changes. AbstractLayoutCache also maintains the expanded state indirectly as it is responsible for maintaining location and sizing information. When a node was changing from !leaf to a leaf, AbstractLayoutCache was not correctly updating its internal cache, which causes the node to expand when it became !leaf again. scott.violet@eng 2000-12-04
04-12-2000