FULL PRODUCT VERSION :
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
A DESCRIPTION OF THE PROBLEM :
Transferring focus from a JRadioButton to the next component with the keyboard causes an Exception to occur when if the component's Window is not the FocusCycleRoot for that component.
The same code works fine on Java 7.
I suspect the code changes from JDK-8033699 caused this regression.
javax.swing.plaf.basic.BasicRadioButtonUI.ButtonGroupInfo.getFocusTransferBaseComponent(boolean)
should probably use the focusCycleRoot for the JRadioButton as 'container', but instead uses the Window that holds the component.
The result is the same if the Window is the FocusCycleRoot, but that is not always the case.
Window container = SwingUtilities.getWindowAncestor(activeBtn);
should probably be replaced by
Container container = activeBtn.getFocusCycleRootAncestor();
REGRESSION. Last worked in version 7u76
ADDITIONAL REGRESSION INFORMATION:
java version "1.7.0_76"
Java(TM) SE Runtime Environment (build 1.7.0_76-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.76-b04, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Run the main method of the class provided. A window appears. Radio button 'Option 1' has the focus.
- Press the tab key
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Focus should be transferred to a different component
ACTUAL -
An exception is thrown and focus was not transferred
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import javax.swing.*;
public class FocusCycleRootTest
{
public static void main(String[] args)
{
JFrame window = new JFrame("Test");
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel rootPanel = new JPanel();
rootPanel.setLayout(new BorderLayout());
JPanel formPanel = new JPanel();
formPanel.setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());
formPanel.setFocusCycleRoot(true);
JRadioButton option1 = new JRadioButton("Option 1", true);
JRadioButton option2 = new JRadioButton("Option 2");
ButtonGroup radioButtonGroup = new ButtonGroup();
radioButtonGroup.add(option1);
radioButtonGroup.add(option2);
formPanel.add(option1);
formPanel.add(option2);
formPanel.add(new JTextField("Another focusable component"));
rootPanel.add(formPanel, BorderLayout.CENTER);
JButton okButton = new JButton("OK");
rootPanel.add(okButton, BorderLayout.SOUTH);
window.add(rootPanel);
window.pack();
window.setVisible(true);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
use the mouse to transfer focus