-
Bug
-
Resolution: Unresolved
-
P3
-
8, 9, 10
-
x86_64
-
linux_ubuntu
FULL PRODUCT VERSION :
java 9-ea and java 1.8.0_111
ADDITIONAL OS VERSION INFORMATION :
Ubuntu 17.07 and Win7
A DESCRIPTION OF THE PROBLEM :
I documented the problem in Stack overflow with a screen capture
and source code to demonstrate the problem
https://stackoverflow.com/questions/44301610/issue-of-jspinner-in-containerorderfocustraversalpolicy
The problem is no indication is available on the jspinner to show it currently has the focus (when using the tab button to change the focus).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) run the program
2) press tab twice to reach the jspinner
3) no indication that the jspinner has the focus (but the up/down keys change the spinner value)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
flashing cursor next to the spinner value to indicate the spinner has the focus
ACTUAL -
no indication of focus
ERROR MESSAGES/STACK TRACES THAT OCCUR :
no crash
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.Component;
import java.awt.Container;
import java.awt.ContainerOrderFocusTraversalPolicy;
import java.util.ArrayList;
public class Focus extends javax.swing.JDialog {
public Focus(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
init();
}
private void init() {
jCheckBox1.setText("java: " + System.getProperty("java.version"));
elementList.add(jButton1);
elementList.add(jCheckBox1);
elementList.add(jSpinner1);
setFocusTraversalPolicy(new CustomFocusTraversalPolicy());
}
private class CustomFocusTraversalPolicy extends ContainerOrderFocusTraversalPolicy {
@Override
public Component getComponentAfter(Container focusCycleRoot, Component aComponent) {
int currentPosition = elementList.indexOf(aComponent);
currentPosition = (currentPosition + 1) % elementList.size();
Component nextC = elementList.get(currentPosition);
/* if( nextC == jSpinner1) {
jSpinner1.requestFocusInWindow();
}*/
return nextC;
}
@Override
public Component getComponentBefore(Container focusCycleRoot, Component aComponent) {
int currentPosition = elementList.indexOf(aComponent);
currentPosition = (elementList.size() + currentPosition - 1) % elementList.size();
return (Component) elementList.get(currentPosition);
}
@Override
public Component getFirstComponent(Container cntnr) {
return (Component) elementList.get(0);
}
@Override
public Component getLastComponent(Container cntnr) {
return (Component) elementList.get(elementList.size() - 1);
}
@Override
public Component getDefaultComponent(Container cntnr) {
return (Component) elementList.get(0);
}
@Override
protected boolean accept(Component aComponent) {
return true;
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jButton1 = new javax.swing.JButton();
jCheckBox1 = new javax.swing.JCheckBox();
jSpinner1 = new javax.swing.JSpinner();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
jButton1.setText("jButton1");
jCheckBox1.setText("jCheckBox1");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jButton1)
.addComponent(jCheckBox1)
.addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(280, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jButton1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jCheckBox1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(195, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the dialog */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Focus dialog = new Focus(new javax.swing.JFrame(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JCheckBox jCheckBox1;
private javax.swing.JSpinner jSpinner1;
// End of variables declaration
ArrayList<Component> elementList = new ArrayList<Component>();
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Comment out setFocusTransversalPolicy.
Not exactly a work around, but it shows the problem
java 9-ea and java 1.8.0_111
ADDITIONAL OS VERSION INFORMATION :
Ubuntu 17.07 and Win7
A DESCRIPTION OF THE PROBLEM :
I documented the problem in Stack overflow with a screen capture
and source code to demonstrate the problem
https://stackoverflow.com/questions/44301610/issue-of-jspinner-in-containerorderfocustraversalpolicy
The problem is no indication is available on the jspinner to show it currently has the focus (when using the tab button to change the focus).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) run the program
2) press tab twice to reach the jspinner
3) no indication that the jspinner has the focus (but the up/down keys change the spinner value)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
flashing cursor next to the spinner value to indicate the spinner has the focus
ACTUAL -
no indication of focus
ERROR MESSAGES/STACK TRACES THAT OCCUR :
no crash
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.Component;
import java.awt.Container;
import java.awt.ContainerOrderFocusTraversalPolicy;
import java.util.ArrayList;
public class Focus extends javax.swing.JDialog {
public Focus(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
init();
}
private void init() {
jCheckBox1.setText("java: " + System.getProperty("java.version"));
elementList.add(jButton1);
elementList.add(jCheckBox1);
elementList.add(jSpinner1);
setFocusTraversalPolicy(new CustomFocusTraversalPolicy());
}
private class CustomFocusTraversalPolicy extends ContainerOrderFocusTraversalPolicy {
@Override
public Component getComponentAfter(Container focusCycleRoot, Component aComponent) {
int currentPosition = elementList.indexOf(aComponent);
currentPosition = (currentPosition + 1) % elementList.size();
Component nextC = elementList.get(currentPosition);
/* if( nextC == jSpinner1) {
jSpinner1.requestFocusInWindow();
}*/
return nextC;
}
@Override
public Component getComponentBefore(Container focusCycleRoot, Component aComponent) {
int currentPosition = elementList.indexOf(aComponent);
currentPosition = (elementList.size() + currentPosition - 1) % elementList.size();
return (Component) elementList.get(currentPosition);
}
@Override
public Component getFirstComponent(Container cntnr) {
return (Component) elementList.get(0);
}
@Override
public Component getLastComponent(Container cntnr) {
return (Component) elementList.get(elementList.size() - 1);
}
@Override
public Component getDefaultComponent(Container cntnr) {
return (Component) elementList.get(0);
}
@Override
protected boolean accept(Component aComponent) {
return true;
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jButton1 = new javax.swing.JButton();
jCheckBox1 = new javax.swing.JCheckBox();
jSpinner1 = new javax.swing.JSpinner();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
jButton1.setText("jButton1");
jCheckBox1.setText("jCheckBox1");
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jButton1)
.addComponent(jCheckBox1)
.addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(280, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jButton1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jCheckBox1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(195, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Focus.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the dialog */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
Focus dialog = new Focus(new javax.swing.JFrame(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JCheckBox jCheckBox1;
private javax.swing.JSpinner jSpinner1;
// End of variables declaration
ArrayList<Component> elementList = new ArrayList<Component>();
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Comment out setFocusTransversalPolicy.
Not exactly a work around, but it shows the problem