The following Swing component encapsulates the functionality required for a credit card entry gui, allowing only numeric entry and automatically switching fields when they get filled. The source is HERE
import java.awt.Dimension;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
/**
* Encapsulates the behaviour required
* for credit card number entry, allowing
* only digits to be entered and shifting
* focus when one of the four fields is filled
*
* @author Charles Johnson
* @version 1.0
*/
class CreditCardPanel extends JPanel {
private JTextField[] fields = new JTextField[4];
// Don't let the fields grow to an ugly size
Dimension MAX_SIZE = new Dimension(1000, 25);
public CreditCardPanel() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
for (int i = 0; i < fields.length; i++) {
fields[i] = new JTextField(4);
fields[i].setDocument(new FourDigitDocument(i));
fields[i].setMaximumSize(MAX_SIZE);
add(fields[i]);
}
}
/**
*
* @return the credit card number
*/
public String getNumber() {
StringBuilder number = new StringBuilder(16);
boolean allFilled = true;
for (int i = 0; i < fields.length; i++) {
if (!isFilled(fields[i])) {
allFilled = false;
break;
} else {
number.append(fields[i].getText());
}
}
if (!allFilled) {
throw new IllegalStateException("Credit card panel not filled");
} else {
return number.toString();
}
}
private boolean isFilled(JTextField f) {
String text = f.getText();
return (text != null) && (text.length() == 4);
}
/**
* Allows four digits only
*
* @author Charles Johnson
* @version 1.0
*/
private class FourDigitDocument extends PlainDocument {
private int index;
public FourDigitDocument(int index) {
this.index = index;
}
/**
*
* @param offs the starting offset >= 0
* @param s the string to insert; does nothing with null/empty strings
* @param as the attributes for the inserted content
*
* @throws BadLocationException the given insert position is not a valid position within the document
*/
@Override
public void insertString(int offs, String s, AttributeSet as)
throws BadLocationException {
if ((s == null) || "".equals(s)) {
return;
}
StringBuilder sb = new StringBuilder(getLength() + s.length());
String newText = sb.append(getText(0, getLength())).insert(offs, s)
.toString();
// Only allow four digits
boolean valid = newText.matches("\\d{1,4}");
if (valid) {
super.insertString(offs, s, as);
}
// Jump to next field if full
if ((newText.length() == 4) && valid && (index <= 2)) {
fields[++index].requestFocus();
}
}
}
}
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
/**
* Encapsulates the behaviour required
* for credit card number entry, allowing
* only digits to be entered and shifting
* focus when one of the four fields is filled
*
* @author Charles Johnson
* @version 1.0
*/
class CreditCardPanel extends JPanel {
private JTextField[] fields = new JTextField[4];
// Don't let the fields grow to an ugly size
Dimension MAX_SIZE = new Dimension(1000, 25);
public CreditCardPanel() {
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
for (int i = 0; i < fields.length; i++) {
fields[i] = new JTextField(4);
fields[i].setDocument(new FourDigitDocument(i));
fields[i].setMaximumSize(MAX_SIZE);
add(fields[i]);
}
}
/**
*
* @return the credit card number
*/
public String getNumber() {
StringBuilder number = new StringBuilder(16);
boolean allFilled = true;
for (int i = 0; i < fields.length; i++) {
if (!isFilled(fields[i])) {
allFilled = false;
break;
} else {
number.append(fields[i].getText());
}
}
if (!allFilled) {
throw new IllegalStateException("Credit card panel not filled");
} else {
return number.toString();
}
}
private boolean isFilled(JTextField f) {
String text = f.getText();
return (text != null) && (text.length() == 4);
}
/**
* Allows four digits only
*
* @author Charles Johnson
* @version 1.0
*/
private class FourDigitDocument extends PlainDocument {
private int index;
public FourDigitDocument(int index) {
this.index = index;
}
/**
*
* @param offs the starting offset >= 0
* @param s the string to insert; does nothing with null/empty strings
* @param as the attributes for the inserted content
*
* @throws BadLocationException the given insert position is not a valid position within the document
*/
@Override
public void insertString(int offs, String s, AttributeSet as)
throws BadLocationException {
if ((s == null) || "".equals(s)) {
return;
}
StringBuilder sb = new StringBuilder(getLength() + s.length());
String newText = sb.append(getText(0, getLength())).insert(offs, s)
.toString();
// Only allow four digits
boolean valid = newText.matches("\\d{1,4}");
if (valid) {
super.insertString(offs, s, as);
}
// Jump to next field if full
if ((newText.length() == 4) && valid && (index <= 2)) {
fields[++index].requestFocus();
}
}
}
}