Don't
Use a KeyLisyener
on text components, it's not an appropriate mechanism for a number of reasons
Do
Use a DocumentFilter
to change the text before it's applied to the physical Document
See Implementing a Document Filter for more details
As a (very quick and basic) example...
public class PropercaseDocumentFilter extends DocumentFilter {
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
text = modify(fb, offset, text, attrs);
super.replace(fb, offset, length, text, attrs);
}
protected String modify(FilterBypass fb, int offset, String text, AttributeSet attrs) throws BadLocationException {
if (text.length() > 0) {
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder(text);
if (doc.getLength() == 0) {
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
} else if (offset > 0 && offset < doc.getLength()) {
if (doc.getText(offset - 1, 1).equals(" ")) {
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
}
} else if (doc.getText(doc.getLength() - 1, 1).equals(" ")) {
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
}
text = sb.toString();
}
return text;
}
}
What this example doesn't do, is change text that is pasted (apart from the first character), you'll need to think about how you want that dealt with and make the appropriate changes
And because I know no one reads the documentation or tutorials...
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
public class JavaApplication100 {
public static void main(String[] args) {
new JavaApplication100();
}
public JavaApplication100() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
JTextField field = new JTextField(10);
((AbstractDocument)field.getDocument()).setDocumentFilter(new PropercaseDocumentFilter());
add(field);
}
}
public class PropercaseDocumentFilter extends DocumentFilter {
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
text = modify(fb, offset, text, attrs);
super.replace(fb, offset, length, text, attrs);
}
protected String modify(FilterBypass fb, int offset, String text, AttributeSet attrs) throws BadLocationException {
if (text.length() > 0) {
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder(text);
if (doc.getLength() == 0) {
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
} else if (offset > 0 && offset < doc.getLength()) {
if (doc.getText(offset - 1, 1).equals(" ")) {
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
}
} else if (doc.getText(doc.getLength() - 1, 1).equals(" ")) {
sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
}
text = sb.toString();
}
return text;
}
}
}