一切正常,直到用户从列表中选择某个值,然后按 ENTER 键,然后我的面板进入下一个步骤 3。我附加了一个键
监听器列出类似 [...]
如果您希望列表中的 Enter 键优先于默认的 Next -> 按钮,那么您必须使用 Key binding 将操作附加到列表中它的重点:
KeyStroke enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
Action updateTextfieldAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
JList list = (JList)evt.getSource();
Object selectedPackage = list.getSelectedValue();
typePackageField.setText((String)selectedPackage );
}
};
list = new JList(new PackagesListModel());
list.getInputMap().put(enterKeyStroke, "enter");
list.getActionMap().put("enter", updateTextfieldAction);
请注意,getInputMap() 是 getInputMap(JComponent.WHEN_FOCUSED) 的快捷方式。这意味着,如果您的列表具有焦点并且按下了 Enter 键,则将执行附加到此击键的操作。
通过这种方式,您的操作将始终优先于下一个按钮的操作,无论此按钮是 default button 还是它使用使用 WHEN_IN_FOCUSED_WINDOW 的键绑定附加了一个操作,如下所示:
JButton button = new JButton(nextStepAction);
button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(enterKeyStroke, "enter");
button.getActionMap().put("enter", nextStepAction);
nextStepAction 将是进入向导下一步的操作。
另见Key bindings vs. key listeners in Java
示例
请参考以下示例。请注意,如果您关注另一个组件但列出执行的默认操作。我已将该按钮设置为框架的根窗格默认按钮,并使用WHEN_IN_FOCUSED_WINDOW 附加了一个操作,只是为了证明WHEN_FOCUSED 操作优先于这些操作。
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
public class Demo {
private JList list;
private JTextField textField;
private void createAndShowGUI() {
KeyStroke enterKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
Action nextStepAction = new AbstractAction("Next") {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "Going to step 3!", "Message", JOptionPane.INFORMATION_MESSAGE);
}
};
Action updateTextfieldAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
textField.setText((String)list.getSelectedValue());
}
};
list = new JList(new String[]{"Item 1", "Item 2", "Item 3"});
list.setPrototypeCellValue("This is a list's prototype cell value.");
list.getInputMap().put(enterKeyStroke, "enter");
list.getActionMap().put("enter", updateTextfieldAction);
textField = new JTextField(15);
JPanel listPanel = new JPanel();
listPanel.add(new JScrollPane(list));
listPanel.add(textField);
JButton button = new JButton(nextStepAction);
button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(enterKeyStroke, "enter");
button.getActionMap().put("enter", nextStepAction);
JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING));
buttonsPanel.add(button);
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(listPanel);
frame.add(buttonsPanel, BorderLayout.PAGE_END);
frame.getRootPane().setDefaultButton(button);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}
其他cmets
请注意,如果您想避免所有这些问题,您可以将ListSelectionListener 附加到您的列表中,并在选择更改时更新文本字段,而根本不需要按 Enter 键。事实上,如果您有权访问下一步操作,您可以根据列表选择启用/禁用它。通过这样做,您将确保如果列表中未选择任何项目,向导将无法继续。恕我直言,这将是处理这种情况的一种更优雅的方式。详情请见Selecting Items in a List。