是的,有一个更简单的方法...
为什么要填充自定义编辑器的 actionmap 而不仅仅是编辑DefaultEditor
?
让我们DefaultEditor
为输入通知事件JFormattedTextField
提供一个自定义操作:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.text.TextAction;
public class OnEnterSpinner extends JPanel {
private final JSpinner spin;
private final JSpinner.DefaultEditor editor;
private final JFormattedTextField field;
private final class OnEnterAction extends TextAction {
private OnEnterAction() {
super(JTextField.notifyAction); //The name of the TextAction. Let's say it is its key.
}
@Override
public void actionPerformed(final ActionEvent actevt) {
if (getFocusedComponent() == field)
System.out.println("The user pressed ENTER for: \"" + field.getText() + "\".");
}
}
private OnEnterSpinner() {
spin = new JSpinner(new SpinnerNumberModel(0, 0, 10000, 1)); //Your values here. Let's say for now this is a spinner for integers.
spin.setPreferredSize(new Dimension(100, 20));
//We need a DefaultEditor (to be able to obtain the JFormattedTextField and customize it).
editor = new JSpinner.DefaultEditor(spin);
field = editor.getTextField();
field.setEditable(true); //Allow user input (obvious reasons).
//And here, you register the custom action!
field.getActionMap().put(JTextField.notifyAction, new OnEnterAction()); //I found the proper key for the map: "notifyAction".
spin.setEditor(editor);
add(spin);
}
public static void main(final String[] args) {
final JFrame frame = new JFrame("OnEnterSpinner demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new OnEnterSpinner());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
此外,如果您需要通过AbstractFormatter
提供给 的自定义来检查输入值的有效性JFormattedTextField
,则只需调用JSpinner#commitEdit()
ENTER:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.text.TextAction;
public class CommitOnEnterSpinner extends JPanel {
private final JSpinner spin;
private final JSpinner.DefaultEditor editor;
private final JFormattedTextField field;
private final class OnEnterAction extends TextAction {
private OnEnterAction() {
super(JTextField.notifyAction);
}
@Override
public void actionPerformed(final ActionEvent actevt) {
if (getFocusedComponent() == field) { //This check may be redundant in this case.
System.out.println("The user pressed ENTER for: \"" + field.getText() + "\".");
try {
//Commit the edits, upon carriage return:
spin.commitEdit();
//If successfull, then handle it as desired:
JOptionPane.showMessageDialog(null, "Yes! This is a valid value.", "OK", JOptionPane.PLAIN_MESSAGE);
}
catch (final ParseException pe) {
//If failed, then handle the unaccepted value:
JOptionPane.showMessageDialog(null, "Sorry, \"" + field.getText() + "\" is not a valid value.", "Oups!", JOptionPane.INFORMATION_MESSAGE);
}
}
}
}
private CommitOnEnterSpinner() {
spin = new JSpinner(new SpinnerNumberModel(0, 0, 10000, 1)); //Your values here. Let's say for now this is a spinner for integers.
spin.setPreferredSize(new Dimension(100, 20));
//We need a DefaultEditor (to be able to obtain the JFormattedTextField and customize it).
editor = new JSpinner.DefaultEditor(spin);
field = editor.getTextField();
field.setEditable(true); //Allow user input (obvious reasons).
//And here, you register the custom action!
field.getActionMap().put(JTextField.notifyAction, new OnEnterAction());
spin.setEditor(editor);
add(spin);
}
public static void main(final String[] args) {
final JFrame frame = new JFrame("CommitOnEnterSpinner demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CommitOnEnterSpinner());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}