Hi folks,
hitting a barrier (again - formatted text fields and me, never will be friends ;-)
The requirement is simple enough: do some stuff when receiving a "value"-changed (aka: commit) and commit on keystroke. The solution seems easy enough too: force a commit on each document change. That works fine (never mind an unsuccessful commit if the user typed in unparseable text, nothing to happen in that case is okay). Except when deleting the last character: no value-changed because most formatters don't map empty string to null value. As I have no control over the formatter (in this case - SwingX extended NumberFormatter does handle it gracefully :-) I came up with a dirty trick: if a forced commit failed and the field's text is empty, set the value to null.
Don't like it ... so any other ideas? Hopefully I'm completely on the wrong track and some kind soul can point me to the right path
Thanks
Jeanette
Below is an example: to see what I mean (and probably described badly :-) delete the numbers until the field is empty. When deleting the last no value changed is fired and transfering the focus to the button restores the text to the last valid value. Uncommenting the dirt makes it behave as I want it.
/*
* Created on 25.11.2010
*
*/
package de.javasoft.swing.jytable;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.ParseException;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
public class FormattedNull {
private JFormattedTextField field;
private JComponent createContent() {
JComponent content = new JPanel();
field = new JFormattedTextField(new Integer(55));
field.setColumns(20);
field.addPropertyChangeListener(getPropertyChangeListener());
field.getDocument().addDocumentListener(getDocumentListener());
content.add(field);
content.add(new JButton("just something focusable"));
return content;
}
protected void maybeCommitEdit(Document document) {
try {
field.commitEdit();
} catch (ParseException e) {
// uncomment to map empty string to null
// if (field.getText().length() == 0) {
// field.setValue(null);
// }
}
}
private PropertyChangeListener getPropertyChangeListener() {
PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("value".equals(evt.getPropertyName()))
matchValueChanged(evt.getNewValue());
}
};
return propertyChangeListener;
}
protected void matchValueChanged(Object value) {
System.out.println("got new value: " + value);
}
private DocumentListener getDocumentListener() {
DocumentListener documentListener = new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
maybeCommitEdit(e.getDocument());
}
@Override
public void insertUpdate(DocumentEvent e) {
maybeCommitEdit(e.getDocument());
}
@Override
public void changedUpdate(DocumentEvent e) {
}
};
return documentListener;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new FormattedNull().createContent());
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
});
}
}