I run into a problem using form default button when it (form) includes JFormattedTextField
.
On a form with such a field, if it happens to have focus (and was changed), you have to press OK twice to get your default button 'pressed'. I think I know why it happens - it's because first Enter gets consumed in Commit processing.
I was also able to make a workaround - if you change Formatter
to commit on each valid edit, then you will get proper behavior, but this a) forces you to specify formatters explicilty, and b) it's not possible to revert to 'old' value (eg. using Escape, or programatically).
Code below demonstrates that: when you run it field at the top commits on each edit and works with single Enter (but you cannot revert), field at the bottom allows reverts, but needs two Enters if edited.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.Date;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.text.DateFormatter;
public class ExFrame extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ExFrame frame = new ExFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public ExFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JFormattedTextField ff_1, ff_2;
//ff_1 has modified behavior of commit on each (valid) edit
DateFormatter f=new DateFormatter();
f.setCommitsOnValidEdit(true);
ff_1 = new JFormattedTextField(f);
ff_1.setValue(new Date());
//ff_2 has default behavior
ff_2 = new JFormattedTextField(new Date());
contentPane.add(ff_1, BorderLayout.NORTH);
contentPane.add(ff_2, BorderLayout.SOUTH);
JButton btnDefault = new JButton("I am default button");
contentPane.add(btnDefault, BorderLayout.CENTER);
getRootPane().setDefaultButton(btnDefault);
}
}
So the question is: Is there a way to get JFormattedTextField
both commit on Enter (so input is verified but only once) and if succesfully validated, activate default button (with single press)?
The basic trick is the fool the keyBinding mechanism into believing that the keyStroke wasn't handled by the textField. To achieve that, we need to subclass the JFormattedTextField and override its processKeyBindings to return false (meaning: "couldn't use").
Something like: