-
Bug
-
Resolution: Not an Issue
-
P4
-
8u65, 9
-
x86
-
generic
FULL PRODUCT VERSION :
ADDITIONAL OS VERSION INFORMATION :
Non-OS specific
A DESCRIPTION OF THE PROBLEM :
When you press the ENTER key in a ComboBox when the popup is not visible, the key press is redirected to the default button. This is fine in most cases (as requested in RFE 4515752), but when you have a component above the ComboBox that wants to handle the ENTER key it never receives it.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the attached source. When the ComboBox has the focus and the popup is not visible, press ENTER.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The panel action should be invoked (shows a dialog containing "Panel enter action performed"). This is how pressing ENTER works in the TextField following the CombBox.
ACTUAL -
The default button action is invoked (shows a dialog containing "Button Action Performed").
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class ComboBoxEnterBinding extends javax.swing.JFrame {
private static final String ENTER_ACTION = "enterAction";
public ComboBoxEnterBinding() {
initComponents();
SwingUtilities.getRootPane(button).setDefaultButton(button);
panel.enableInputMethods(true);
panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), ENTER_ACTION);
Action enterAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(panel, "Panel enter action performed");
}
};
panel.getActionMap().put(ENTER_ACTION, enterAction);
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
button = new javax.swing.JButton();
panel = new javax.swing.JPanel();
comboBox = new javax.swing.JComboBox();
jTextField1 = new javax.swing.JTextField();
editableCheckbox = new javax.swing.JCheckBox();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
button.setText("Default");
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonActionPerformed(evt);
}
});
panel.setBorder(javax.swing.BorderFactory.createTitledBorder("Panel Handles ENTER Key"));
comboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "ENTER should propagate up to panel", "Even when editable", "Unless popup is open", "And then it should close without propagating" }));
javax.swing.GroupLayout panelLayout = new javax.swing.GroupLayout(panel);
panel.setLayout(panelLayout);
panelLayout.setHorizontalGroup(
panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(comboBox, 0, 359, Short.MAX_VALUE)
.addComponent(jTextField1))
.addContainerGap())
);
panelLayout.setVerticalGroup(
panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(comboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
editableCheckbox.setText("Editable ComboBox");
editableCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
editableCheckboxActionPerformed(evt);
}
});
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(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(editableCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(button)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(panel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(editableCheckbox)
.addComponent(button))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
JOptionPane.showMessageDialog(this, "Button Action Performed");
}
private void editableCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
comboBox.setEditable(editableCheckbox.isSelected());
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ComboBoxEnterBinding().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton button;
private javax.swing.JComboBox comboBox;
private javax.swing.JCheckBox editableCheckbox;
private javax.swing.JTextField jTextField1;
private javax.swing.JPanel panel;
// End of variables declaration
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
A messy workaround for an editable ComboBox is to add a key listener to the editor component and redispatch the ENTER key pressed event to the parent of the combobox.
This could be fixed by modifying BasicComboBoxUI.Actions.actionPerformed to dispatch the ENTER pressed KeyEvent to the parent of the ComboBox rather than directly invoking the root pane ENTER action. In cases where there is no ENTER key binding in containing components, this would still invoke the default button action when processing key bindings for the root pane.
ADDITIONAL OS VERSION INFORMATION :
Non-OS specific
A DESCRIPTION OF THE PROBLEM :
When you press the ENTER key in a ComboBox when the popup is not visible, the key press is redirected to the default button. This is fine in most cases (as requested in RFE 4515752), but when you have a component above the ComboBox that wants to handle the ENTER key it never receives it.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the attached source. When the ComboBox has the focus and the popup is not visible, press ENTER.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The panel action should be invoked (shows a dialog containing "Panel enter action performed"). This is how pressing ENTER works in the TextField following the CombBox.
ACTUAL -
The default button action is invoked (shows a dialog containing "Button Action Performed").
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class ComboBoxEnterBinding extends javax.swing.JFrame {
private static final String ENTER_ACTION = "enterAction";
public ComboBoxEnterBinding() {
initComponents();
SwingUtilities.getRootPane(button).setDefaultButton(button);
panel.enableInputMethods(true);
panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).
put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), ENTER_ACTION);
Action enterAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(panel, "Panel enter action performed");
}
};
panel.getActionMap().put(ENTER_ACTION, enterAction);
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
button = new javax.swing.JButton();
panel = new javax.swing.JPanel();
comboBox = new javax.swing.JComboBox();
jTextField1 = new javax.swing.JTextField();
editableCheckbox = new javax.swing.JCheckBox();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
button.setText("Default");
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
buttonActionPerformed(evt);
}
});
panel.setBorder(javax.swing.BorderFactory.createTitledBorder("Panel Handles ENTER Key"));
comboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "ENTER should propagate up to panel", "Even when editable", "Unless popup is open", "And then it should close without propagating" }));
javax.swing.GroupLayout panelLayout = new javax.swing.GroupLayout(panel);
panel.setLayout(panelLayout);
panelLayout.setHorizontalGroup(
panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(comboBox, 0, 359, Short.MAX_VALUE)
.addComponent(jTextField1))
.addContainerGap())
);
panelLayout.setVerticalGroup(
panelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(comboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 19, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
editableCheckbox.setText("Editable ComboBox");
editableCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
editableCheckboxActionPerformed(evt);
}
});
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(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(editableCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(button)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(panel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(editableCheckbox)
.addComponent(button))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
JOptionPane.showMessageDialog(this, "Button Action Performed");
}
private void editableCheckboxActionPerformed(java.awt.event.ActionEvent evt) {
comboBox.setEditable(editableCheckbox.isSelected());
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new ComboBoxEnterBinding().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton button;
private javax.swing.JComboBox comboBox;
private javax.swing.JCheckBox editableCheckbox;
private javax.swing.JTextField jTextField1;
private javax.swing.JPanel panel;
// End of variables declaration
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
A messy workaround for an editable ComboBox is to add a key listener to the editor component and redispatch the ENTER key pressed event to the parent of the combobox.
This could be fixed by modifying BasicComboBoxUI.Actions.actionPerformed to dispatch the ENTER pressed KeyEvent to the parent of the ComboBox rather than directly invoking the root pane ENTER action. In cases where there is no ENTER key binding in containing components, this would still invoke the default button action when processing key bindings for the root pane.