United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6294075 : JList double highlights entries when selection pops up a modal dialog

Details
Type:
Bug
Submit Date:
2005-07-05
Status:
Closed
Updated Date:
2011-02-16
Project Name:
JDK
Resolved Date:
2007-04-13
Component:
client-libs
OS:
windows_vista,windows_2000
Sub-Component:
java.awt
CPU:
x86
Priority:
P3
Resolution:
Won't Fix
Affected Versions:
5.0u3,6
Fixed Versions:

Related Reports
Duplicate:
Relates:
Relates:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.4.2_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_05-b04)
Java HotSpot(TM) Client VM (build 1.4.2_05-b04, mixed mode)

java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
windows2000, linux (fedoracore 2)
(works on Mac OS x 10.3.9)

A DESCRIPTION OF THE PROBLEM :
I have a JList  with the following entries: "one", "two", "THREE", "four".
SINGLE_SELECTION model. When the user selects "THREE", it pops up
a modal dialog. If I go down the list, selecting each entry successively,
when I choose "THREE", the JList highlights my previous selection (e.g. "two")
and the current selection (i.e. "THREE"), even though I have set it to
SINGLE_SELECTION.

I have observed this on windows2000, and linux (fedoracore2), but
not on Mac OS X 10.3.9.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the included program, select each JList entry in order.  Each item will be highlighted, except when "THREE" is selected. A modal dialog will pop up, leaving both "two" and "THREE" highlighted.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
"two" should not be highlighted, only "THREE".
ACTUAL -
both "two" and "THREE" are highlighted.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class TestJList extends JFrame implements ListSelectionListener, FocusListener
{
    private static TestJList sTest;

    private JList list;
    private JScrollPane scroll;
    private String fCurrentItem;
    
    public TestJList()
    {
		JToolBar tool = new JToolBar();
        sTest = this;
        
        setTitle("Test Frame");
        JPanel innerPanel = new JPanel(new BorderLayout());
        
        list = new JList();

        scroll = new JScrollPane();
		scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scroll.getVerticalScrollBar().setFocusable(false);
		scroll.setBorder(BorderFactory.createLoweredBevelBorder());

		list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        
        tool.add(scroll);
		scroll.getViewport().add(list, null);

		list.addListSelectionListener(this);
		list.addFocusListener(this);
		//list.setEnabled(false);
		 String[] data = {"one", "two", "THREE", "four"};
		list.setListData(data);

        innerPanel.add(tool, BorderLayout.NORTH);
        setTitle("Test Combo");
        JTextArea textArea = new JTextArea();
        textArea.setLineWrap(true);
        textArea.setPreferredSize(new Dimension(400,400));
        innerPanel.add(textArea, BorderLayout.CENTER);
        getContentPane().add(innerPanel);
        sTest.setSize(400, 400);
        sTest.setVisible(true);
        
    }
    

    public static void main(String[] args)
    {
        new TestJList();
    }

    public void focusGained(FocusEvent event)
	{
		Object      eventSource = event.getSource();
		//System.out.println("focusGained("+eventSource+")");
	}

    public void focusLost(FocusEvent event)
	{
		Object      eventSource = event.getSource();
		//System.out.println("focusLost("+eventSource+")");
	}

    public void valueChanged(ListSelectionEvent event)
	{
		Object      eventSource = event.getSource();
		//System.out.println("focusLost("+eventSource+")");

		if (eventSource == list)
		{
			int idx = list.getSelectedIndex();
System.out.println("idx:"+idx);
			if (idx == 2)
			popupdialog();
		}
	}

	public void popupdialog()
	{
		dialog d = new dialog(this);
		d.pack();
		d.show();
	}

	public class dialog extends JDialog implements ActionListener
	{
		private JPanel          Panel_Content = new JPanel();
		private JPanel          Panel_Buttons = new JPanel();
		private JButton         button = new JButton();

		dialog(Frame owner)
		{
			super(owner);
			try {jbInit();} catch (Exception e){e.printStackTrace();}
		}

    	private void jbInit() throws Exception
    	{
        	// init the ui
        	this.setModal(true);
        	this.setTitle("dialog");

			Panel_Content.setLayout(new GridBagLayout());
			Panel_Content.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));

			button.setText("OK");
			Panel_Buttons.setLayout(new GridBagLayout());
			Panel_Buttons.add(button, new GridBagConstraints(0, 0, 0, 0, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 10, 0, 0), 0, 0));
			Panel_Content.add(Panel_Buttons, new GridBagConstraints(0, 3, 2, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(20, 0, 0, 0), 0, 0));
			this.getContentPane().add(Panel_Content, BorderLayout.CENTER);

			button.addActionListener(this);
		}

		public void actionPerformed(ActionEvent event)
		{
			Object      eventSource = event.getSource();
			if (eventSource == button)
			{
				hide();
			}
        }
	}
}

---------- END SOURCE ----------
###@###.### 2005-07-05 09:43:19 GMT

                                    

Comments
EVALUATION

The problem here is that the developer's listener responsible for showing the modal dialog is notified before Swing's internal listener for repainting the list. This is an unfortunate problem with listeners invoking modal dialogs. There is a Swing RFE for listener ordering that may eventually make this problem easier to work-around.

I would like to suggest, however, that AWT consider a non-blocking show() variant for modal dialogs. I don't beleive it's necessary for show() to always block as it does now. Using such a variant in this test case would solve the problem. I'v mentioned this to ###@###.###.

Lastly, the developer may solve this by calling repaint() on the list before showing the dialog.
                                     
2005-08-03
WORK AROUND

Call repaint() on the list before showing the dialog.
                                     
2005-08-03
EVALUATION

Standard way to workaround the problem is to show the modal dialog in a separate InvokeLater() block. This approach can also be used in many other situations, like showing a modal dialog on a button press.

At the same time, I doubt we need an unblocking variant of show() for modal dialogs. That's why I'm closing this change request.
                                     
2007-04-13



Hardware and Software, Engineered to Work Together