JDK-7178770 : DefaultTreeCellEditor does not dispatch mouseEvents to child components
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 7
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2012-06-21
  • Updated: 2014-01-14
  • Resolved: 2014-01-14
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.
JDK 9
9Resolved
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) Client VM (build 23.1-b03, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Windows XP SP3, WIndows 7

A DESCRIPTION OF THE PROBLEM :
Jtree has uses a custom CellEditor that returns  a JPanel containing a checkbox and a label.
In java 1.5 and java1.6 one mouseclick will trigger the actionlistener in the checkbox. Java 1.7 breaks comptibility. The first click will only activate the celleditor and a second click is needed to selct the checkbox.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a Jtree with a CellEdito that returns a JPanel with a nested checkbox.
Now run your program an click on the checkbox.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
One click will select a checkbox
ACTUAL -
First click does not select the checkbox, a second click is needed.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import java.util.Vector;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellEditor;
import javax.swing.tree.DefaultTreeCellRenderer;

public class SimpleTreeTest extends JFrame
{

	public static void main(String[] args)
	{
		SimpleTreeTest stt = new SimpleTreeTest();
		stt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		stt.setSize(250, 250);
		stt.setVisible(true);
	}

	public SimpleTreeTest()
	{
		Vector<Person> v = new Vector<Person>();
		v.addElement(new Person(false, "john"));
		v.addElement(new Person(false, "peter"));
		v.addElement(new Person(false, "mike"));
		v.addElement(new Person(false, "sandra"));

		JTree tree = new JTree(v);
		tree.setRootVisible(true);
		tree.setEditable(true);
		tree.setCellRenderer(new CheckboxTreeRenderer());
		tree.setCellEditor(new CheckboxCellEditor(tree,
				new CheckboxTreeRenderer()));
		JScrollPane jsp = new JScrollPane(tree);
		getContentPane().add(jsp);
	}

	class Person
	{
		boolean alive;
		String name;

		private Person(boolean alive, String name)
		{
			super();
			this.alive = alive;
			this.name = name;
		}

	}

	class CheckboxTreeRenderer extends DefaultTreeCellRenderer
	{

		public Component getTreeCellRendererComponent(JTree tree, Object value,
				boolean isSelected, boolean expanded, boolean leaf, int row,
				boolean hasFocus)
		{

			if (value instanceof DefaultMutableTreeNode)
			{
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
				if (node.getUserObject() instanceof Person)
				{
					Person p = (Person) node.getUserObject();
					JCheckBox checkBox = new JCheckBox();
					JPanel panel = new JPanel(new BorderLayout());
					JLabel label = new JLabel();
					label.setText(p.name);
					checkBox.setSelected(p.alive);
					panel.add(checkBox, BorderLayout.WEST);
					panel.add(label, BorderLayout.CENTER);
					return panel;
				}
				else
				{
					Object o = node.getUserObject();
					JLabel label = new JLabel();
					label.setText(o.toString());
					return label;
				}

			}
			return new JLabel("unknown");

		}

	}

	class CheckboxCellEditor extends DefaultTreeCellEditor
	{

		JPanel panel;
		JCheckBox checkBox;

		public CheckboxCellEditor(JTree tree, DefaultTreeCellRenderer renderer)
		{
			super(tree, renderer);
			// TODO Auto-generated constructor stub
		}

		public boolean isCellEditable(EventObject evt)
		{
			return true;
		}

		/** possible workaround for java1.7 to allow singleclick on checkbox */
		/*
		public boolean shouldSelectCell(EventObject anEvent)
		{
			if (anEvent instanceof MouseEvent)
			{
				MouseEvent me = (MouseEvent) anEvent;
				Component c = SwingUtilities.getDeepestComponentAt(me
						.getComponent(), me.getX(), me.getY());
				// System.out.println("deeepest component from tree "+ c);
				final MouseEvent ev = SwingUtilities.convertMouseEvent(me
						.getComponent(), me, panel);

				SwingUtilities.invokeLater(new Runnable()
				{
					public void run()
					{
						// panel.dispatchEvent(ev); //does not work ???????????
						// so the do the click directly through clickmethod
						if (checkBox.contains(ev.getPoint()))
						{
							System.out.println("clicked in checkbox");
							checkBox.doClick();
						}
					}
				});
			}
			return false;
		}
		*/

		public Component getTreeCellEditorComponent(JTree tree, Object value,
				boolean isSelected, boolean expanded, boolean leaf, int row)
		{
			if (value instanceof DefaultMutableTreeNode)
			{
				DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
				if (node.getUserObject() instanceof Person)
				{
					final Person p = (Person) node.getUserObject();
					checkBox = new JCheckBox();
					checkBox.addActionListener(new ActionListener()
					{

						public void actionPerformed(ActionEvent e)
						{
							System.out.println("got event");
							p.alive = (!(p.alive));

						}

					});

					panel = new JPanel(new BorderLayout());
					panel.addMouseListener(new MouseAdapter()
					{

						public void mouseClicked(MouseEvent arg0)
						{
							System.out.println("MouseEvent " + arg0);

						}
					});

					JLabel label = new JLabel();
					label.setText(p.name);
					checkBox.setSelected(p.alive);
					panel.add(checkBox, BorderLayout.WEST);
					panel.add(label, BorderLayout.CENTER);
					return panel;
				}
				else
				{
					Object o = node.getUserObject();
					JLabel label = new JLabel();
					label.setText(o.toString());
					return label;
				}

			}
			return new JLabel("unknown");

		}

	}

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
public boolean shouldSelectCell(EventObject anEvent)
		{
			if (anEvent instanceof MouseEvent)
			{
				MouseEvent me = (MouseEvent) anEvent;
				Component c = SwingUtilities.getDeepestComponentAt(me
						.getComponent(), me.getX(), me.getY());
				// System.out.println("deeepest component from tree "+ c);
				final MouseEvent ev = SwingUtilities.convertMouseEvent(me
						.getComponent(), me, panel);

				SwingUtilities.invokeLater(new Runnable()
				{
					public void run()
					{
						// panel.dispatchEvent(ev); //does not work ???????????
						// so the do the click directly through clickmethod
						if (checkBox.contains(ev.getPoint()))
						{
							System.out.println("clicked in checkbox");
							checkBox.doClick();
						}
					}
				});
			}
			return false;
		}

Comments
These are all approved for deferral to JDK 9 so you can update the FixVersion to state JDK 9. Kind regards, Mathias
29-08-2013

These are all approved for deferral to JDK 9 so you can update the FixVersion to state JDK 9. Kind regards, Mathias
29-08-2013

These are all approved for deferral to JDK 9 so you can update the FixVersion to state JDK 9. Kind regards, Mathias
29-08-2013

Converted "8-client-defer-candidate" label to "8-defer-request" by SQE' OK.
15-08-2013

*This is anti-deferral criteria list*: - P2 -------------- Engineering's Criteria ------------------------------------- - tck-red labeled - conformance labeled - P3 regressions reported/labeled against jdk8 - findbugs, parfait, eht labeled bugs - CAP <1 year reported - netbeans <1 year reported Victor ----------------- SQE's OK --------------------------------- Yes, we are ok with that thanks, Mikhail
15-08-2013

8-defer-request: This is the issue reproduced from 7 GA, this is not a regression in 8, requesting to defer because there are no customer escalations on this issue.
17-06-2013