Name: sv35042 Date: 10/18/2002
FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)
FULL OPERATING SYSTEM VERSION :
4NT 3.01A Windows NT 4.00
A DESCRIPTION OF THE PROBLEM :
First of all, this problem does not appear in jdk 1.3.1.
In version 1.4 (and also in 1.4.0_01), when a component is
removed from a container, the container tries to set the
focus on to the next component, if the component being
removed had the focus. If the next component in the focus
traversal list is disabled, then the following exception is
thrown.
java.lang.IllegalArgumentException: focusCycleRoot is not a
focus cyle root of a Component
at
javax.swing.SortingFocusTraversalPolicy.getComponentAfter
(SortingFocusTraversalPolicy.java:195)
at
javax.swing.LayoutFocusTraversalPolicy.getComponentAfter
(LayoutFocusTraversalPolicy.java:85)
at
javax.swing.LegacyGlueFocusTraversalPolicy.getComponentAfter
(LegacyGlueFocusTraversalPolicy.java:63)
at java.awt.Component.nextFocusHelper
(Component.java:6156)
at java.awt.Container.nextFocusHelper
(Container.java:2197)
at java.awt.Component.removeNotify
(Component.java:5436)
at java.awt.Container.removeNotify
(Container.java:1883)
at javax.swing.JComponent.removeNotify
(JComponent.java:4286)
at java.awt.Container.removeAll(Container.java:609)
.
.
.
REGRESSION. Last worked in version 1.3.1
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.Create a panel and add 3 JTextFields to it. Let's call
them text1, text2 and text3
2.text1.setNextFocusableComponent(text3);
3.text3.setEnabled(false); //so that control cannot really
go to text3
4.add the panel to a frame and show it
5.Now try to remove all the components from frame (say when
someone tries to close the frame. There is a reason why we
are having to do this instead of disposing the frame
directly). The following method would do this. (Pass
reference to the frame as a parameter to this method):
public static void removeComponentsFromContainer
(Container c) {
if (c == null) return;
Component[] components = c.getComponents();
for (int i = 0; i < components.length; i++) {
if (components[i] instanceof Container) {
removeComponentsFromContainer((Container)
components[i]);
}
}
c.removeAll();
}
This throws the exception mentioned above. This piece of
code does not throw any exception under jdk 1.3.
(full source code included)
EXPECTED VERSUS ACTUAL BEHAVIOR :
Excepted result: The code should be able to remove all the
components
Actual result: Exception being thrown
ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.IllegalArgumentException: focusCycleRoot is not a focus cyle root of
a Component
at javax.swing.SortingFocusTraversalPolicy.getComponentAfter
(SortingFocusTraversalPolicy.java:195)
at javax.swing.LayoutFocusTraversalPolicy.getComponentAfter
(LayoutFocusTraversalPolicy.java:85)
at javax.swing.LegacyGlueFocusTraversalPolicy.getComponentAfter
(LegacyGlueFocusTraversalPolicy.java:63)
at java.awt.Component.nextFocusHelper(Component.java:6156)
at java.awt.Container.nextFocusHelper(Container.java:2197)
at java.awt.Component.removeNotify(Component.java:5436)
at java.awt.Container.removeNotify(Container.java:1883)
at javax.swing.JComponent.removeNotify(JComponent.java:4286)
at java.awt.Container.removeAll(Container.java:609)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class CloseTest
{
public static JPanel getPanel()
{
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(4,2));
JLabel label1 = new JLabel("label 1");
JLabel label2 = new JLabel("label 2");
JLabel label3 = new JLabel("label 3");
JTextField text1 = new JTextField("label 1 text");
JTextField text2 = new JTextField("label 2 text");
JTextField text3 = new JTextField("label 3 text");
panel.add(label1);
panel.add(text1);
panel.add(label2);
panel.add(text2);
panel.add(label3);
panel.add(text3);
label2.requestFocus();
panel.setBorder(BorderFactory.createEtchedBorder());
text1.setNextFocusableComponent(text3);
text3.setEnabled(false);
return panel;
}
public static void removeComponentsFromContainer(Container c)
{
if (c == null) return;
Component[] components = c.getComponents();
for (int i = 0; i < components.length; i++)
{
if (components[i] instanceof Container)
{
removeComponentsFromContainer((Container) components[i]);
}
}
c.removeAll();
}
public static void main(String[] args)
{
try
{
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch (Exception e)
{
e.printStackTrace();
}
final JFrame frame = new JFrame("Close Test");
Container container = frame.getContentPane();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
removeComponentsFromContainer(frame);
System.exit(0);
}
});
container.add(getPanel());
frame.setLocation(400,300);
frame.setSize(300,150);
frame.show();
}
}
---------- END SOURCE ----------
Release Regression From : 1.4
The above release value was the last known release where this
bug was known to work. Since then there has been a regression.
(Review ID: 153584)
======================================================================