JTextField that has inner fields or preformated format, something like the ip field in windows
I want to create a text field that will be for dates and will have dd.mm.YYYY
format. Now what I want the user to type only the numbers, not the dots to. So the field would be like:
_ _. _ _ . _ _ _ _
So when the user wants to type the date: 15.05.2010 for example, he will only type the numbers in the sequence 15052010.
Also I would like, when he presses on left or right arrow, the cursor to go from one field (not JTextField, but field in the JTextField) to the next. So lets say I have JTextField with this text in it: 15.05.2010
If the user is on the beginning and he presses the right arrow, the cursor should go to the .05
field.
I hope you understand me because right now I don't have any idea how to make this, or at l开发者_C百科east how to look for it on google.
Well, here are 4 classes that solve your problem. In my case its version control but IP address has the same structure and its easy to modify it.
package com.demo.textfield.version;
import javax.swing.text.Document;
/**
* create documents for text fields
*/
public class DocumentsFactory {
private DocumentsFactory() {}
public static Document createIntDocument() {
return createIntDocument(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public static Document createIntDocument(int maxValue) {
return createIntDocument(maxValue, Integer.MAX_VALUE);
}
public static Document createIntDocument(int maxValue, int maxLength) {
IntDocument intDocument = new IntDocument();
intDocument.setMaxVal(maxValue);
intDocument.setMaxLength(maxLength);
return intDocument;
}
}
in the followed class we define view:
package com.demo.textfield.version;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JPanel;
public class GridbagPanel extends JPanel {
private static final long serialVersionUID = 1L;
public static final Insets NO_INSETS = new Insets(0, 0, 0, 0);
public GridBagConstraints constraints;
private GridBagLayout layout;
public GridbagPanel() {
layout = new GridBagLayout();
constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = NO_INSETS;
setLayout(layout);
}
public void setHorizontalFill() {
constraints.fill = GridBagConstraints.HORIZONTAL;
}
public void setNoneFill() {
constraints.fill = GridBagConstraints.NONE;
}
public void add(Component component, int x, int y, int width, int
height, int weightX, int weightY) {
GridBagLayout gbl = (GridBagLayout) getLayout();
gbl.setConstraints(component, constraints);
add(component);
}
public void add(Component component, int x, int y, int width, int height) {
add(component, x, y, width, height, 0, 0);
}
public void setBothFill() {
constraints.fill = GridBagConstraints.BOTH;
}
public void setInsets(Insets insets) {
constraints.insets = insets;
}
}
We use a plain document that contains our main logic (your changes should be here):
package com.demo.textfield.version;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
/**
* a class for positive integers
*/
public class IntDocument extends PlainDocument {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final String NUMERIC = "0123456789";
private int maxVal = -1;
private int maxLength = -1;
public IntDocument() {
this.maxVal = -1;
maxVal = Integer.MAX_VALUE;
maxLength = Integer.MAX_VALUE;
}
public void setMaxLength(int maxLength) {
if (maxLength < 0)
throw new IllegalArgumentException("maxLength<0");
this.maxLength = maxLength;
}
public void setMaxVal(int maxVal) {
this.maxVal = maxVal;
}
public void insertString
(int offset, String str, AttributeSet attr)
throws BadLocationException {
if (str == null)
return;
if (str.startsWith(" ") && offset == 0) {
beep();
str = "";
}
if (!isValidForAcceptedCharsPolicy(str))
return;
if (validateLength(offset, str) == false)
return;
if (!isValidForMaxVal(offset, str))
return;
super.insertString(offset, str, attr);
}
public boolean isValidForAcceptedCharsPolicy(String str) {
if (str.equals("")) {
beep();
return false;
}
for (int i = 0; i < str.length(); i++) {
if (NUMERIC.indexOf(String.valueOf(str.charAt(i))) == -1) {
beep();
return false;
}
}
return true;
}
public boolean isValidForMaxVal(int offset, String toAdd) {
String str_temp;
//String str_text = "";
String str1 = "";
String str2 = "";
try {
str1 = getText(0, offset);
str2 = getText(offset, getLength() - offset);
} catch (Exception e) {
e.printStackTrace();
}
int i_value;
str_temp = str1 + toAdd + str2;
//str_temp = str_temp.trim();
i_value = Integer.parseInt(str_temp);
if (i_value > maxVal) {
beep();
return false;
} else
return true;
}
private boolean validateLength(int offset, String toAdd) {
String str_temp;
//String str_text = "";
String str1 = "";
String str2 = "";
try {
str1 = getText(0, offset);
str2 = getText(offset, getLength() - offset);
} catch (Exception e) {
e.printStackTrace();
}
str_temp = str1 + toAdd + str2;
if (maxLength < str_temp.length()) {
beep();
return false;
} else
return true;
}
private void beep() {
//java.awt.Toolkit.getDefaultToolkit().beep();
}
}
And this is last one with main method that implements all above posted code and you get pretty good view. In my case I used list of 4 text fields separated by dot. You can jump from one "window" to another by using arrows or tab or dot or if your number length reached 4. It will work with implementation of FocusAdapter
class:
package com.demo.textfield.version;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.FocusManager;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
/**
* diplays an version text field
*/
![enter image description here][1]public class VersionTextField extends GridbagPanel {
private static final long serialVersionUID = 1L;
/**
* a text field for each byte
*/
private JTextField[] textFields;
/**
* dots between text fields
*/
private JLabel[] dotsLabels;
/**
* used to calculate enable/disable color; never shown
*/
private static JTextField sampleTextField = new JTextField();
/**
* listen to changes in the byte fields
*/
private MyDocumentListener documentListener;
/**
* list of key listeners
*/
private List<KeyListener> keyListenersList;
/**
* List of Focus Adapter that select all data in JTextFiled during action
* */
private List<FocusAdapter> focusAdapterList;
/**
* list of key listeners
*/
private List<FocusListener> focusListenersList;
private int maxHeight = 0;
public VersionTextField() {
this(4);
}
/**
* @param byteCount
* number of bytes to display
*/
private VersionTextField(int byteCount) {
textFields = new JTextField[byteCount];
for (int i = 0; i < textFields.length; i++) {
textFields[i] = new JTextField(4);
}
//layout
//constraints.insets = new Insets(0, 0, 0, 0);
List<JLabel> dotsLabelsList = new ArrayList<JLabel>();
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setHorizontalAlignment(JTextField.CENTER);
Document document = DocumentsFactory.createIntDocument(9999);
textField.setDocument(document);
if (i < textFields.length-1) {
add(textField, i * 2, 0, 1, 1);
if (textField.getPreferredSize().height > maxHeight)
maxHeight = textField.getPreferredSize().height;
JLabel label = new JLabel(".");
add(label, (i * 2) + 1, 0, 1, 1);
if (label.getPreferredSize().height > maxHeight)
maxHeight = label.getPreferredSize().height;
dotsLabelsList.add(label);
} else
add(textField, i * 2, 0, 1, 1);
}
//dotsLabels = new JLabel[dotsLabelsList.size()];
dotsLabels = new JLabel[dotsLabelsList.size()];
dotsLabels = dotsLabelsList.toArray(dotsLabels);
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setBorder(BorderFactory.createEmptyBorder());
}
//init
Color backgroundColor = UIManager.getColor("TextField.background");
setBackground(backgroundColor);
Border border = UIManager.getBorder("TextField.border");
setBorder(border);
//register listeners
for (int i = 1; i < textFields.length; i++) {
JTextField field = textFields[i];
field.addKeyListener(new BackKeyAdapter());
}
documentListener = new MyDocumentListener();
for (int i = 0; i < textFields.length - 1; i++) {
JTextField field = textFields[i];
field.getDocument().addDocumentListener(documentListener);
field.addKeyListener(new ForwardKeyAdapter());
}
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.addKeyListener(new MyKeyListener());
}
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.addFocusListener(new MyFocusAdapter());
}
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.addFocusListener(new MyFocusAdapter());
}
keyListenersList = new ArrayList<KeyListener>();
focusListenersList = new ArrayList<FocusListener>();
focusAdapterList = new ArrayList<FocusAdapter>();
}
public synchronized void addKeyListener(KeyListener l) {
super.addKeyListener(l);
keyListenersList.add(l);
}
public synchronized void addFocusListener(FocusListener l) {
super.addFocusListener(l);
if (focusListenersList != null)
focusListenersList.add(l);
}
public synchronized void removeKeyListener(KeyListener l) {
super.removeKeyListener(l);
if (focusListenersList != null)
keyListenersList.remove(l);
}
public synchronized void removeFocusListener(FocusListener l) {
super.removeFocusListener(l);
keyListenersList.remove(l);
}
public void setEnabled(boolean b) {
super.setEnabled(b);
sampleTextField.setEnabled(b);
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setEnabled(b);
}
for (int i = 0; i < dotsLabels.length; i++) {
JLabel dotsLabel = dotsLabels[i];
dotsLabel.setEnabled(b);
}
setBackground(sampleTextField.getBackground());
setForeground(sampleTextField.getForeground());
setBorder(sampleTextField.getBorder());
}
public void requestFocus() {
super.requestFocus();
textFields[0].requestFocus();
}
public void setEditable(boolean b) {
sampleTextField.setEditable(b);
setBackground(sampleTextField.getBackground());
setForeground(sampleTextField.getForeground());
setBorder(sampleTextField.getBorder());
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setEditable(b);
}
for (int i = 0; i < dotsLabels.length; i++) {
JLabel dotsLabel = dotsLabels[i];
dotsLabel.setForeground(sampleTextField.getForeground());
}
}
public boolean isFieldEmpty() {
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
String sCell = textField.getText().trim();
if (!(sCell.equals("")))
return false;
}
return true;
}
public Dimension getPreferredSize() {
if (super.getPreferredSize().height > maxHeight)
maxHeight = super.getPreferredSize().height;
return new Dimension(super.getPreferredSize().width, maxHeight);
}
/**
* clears current text in text fiekd
*/
private void reset() {
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.getDocument().removeDocumentListener(documentListener);
textField.setText("");
textField.getDocument().addDocumentListener(documentListener);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("test");
VersionTextField ipTextField = new VersionTextField();
ipTextField.setText("9.1.23.1479");
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(ipTextField);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void setText(String version) {
if (version == null || "".equals(version) || "null".equals(version))
reset();
else {
setVer(version.split("[.]"));
}
}
private void setVer(String[] ver) {
if (ver == null) {
reset();
return;
}
Enumeration<String> enumeration = Collections.enumeration(Arrays.asList(ver));
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
String s = (String) enumeration.nextElement();
textField.getDocument().removeDocumentListener(documentListener);
textField.setText(s);
textField.getDocument().addDocumentListener(documentListener);
}
}
public void setToolTipText(String toolTipText) {
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
textField.setToolTipText(toolTipText);
}
}
private class MyDocumentListener implements DocumentListener {
@Override
public void insertUpdate(DocumentEvent e) {
Document document = e.getDocument();
try {
JTextField textField = (JTextField) FocusManager.getCurrentManager().getFocusOwner();
String s = document.getText(0, document.getLength());
if (s.length() == 4){ // && textField.getCaretPosition() == 2) {
textField.transferFocus();
}
} catch (BadLocationException e1) {
e1.printStackTrace();
return;
}
}
public void removeUpdate(DocumentEvent e) {
}
@Override
public void changedUpdate(DocumentEvent e) {
// Document document = e.getDocument();
// try {
// Component component = FocusManager.getCurrentManager().getFocusOwner();
// String s = document.getText(0, document.getLength());
//
// // get selected integer
// int valueInt = Integer.parseInt(s);
//
// if (valueInt > 25) {
// component.transferFocus();
// }
//
// } catch (BadLocationException e1) {
// e1.printStackTrace();
// return;
// }
}
}
private class BackKeyAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
JTextField textField = (JTextField) e.getComponent();
if (textField.getCaretPosition() == 0
&& KeyEvent.VK_LEFT == e.getKeyCode()
&& e.getModifiers() == 0)
textField.transferFocusBackward();
if (textField.getCaretPosition() == 0
&& KeyEvent.VK_BACK_SPACE == e.getKeyCode()
&& e.getModifiers() == 0) {
textField.transferFocusBackward();
}
}
}
private class ForwardKeyAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
JTextField textField = (JTextField) e.getComponent();
if (KeyEvent.VK_RIGHT == e.getKeyCode() && e.getModifiers() == 0) {
int length = textField.getText().length();
int caretPosition = textField.getCaretPosition();
if (caretPosition == length) {
textField.transferFocus();
e.consume();
}
}
if (e.getKeyChar() == '.' &&
textField.getText().trim().length() != 0) {
textField.setText(textField.getText().trim());
textField.transferFocus();
e.consume();
}
}
}
/**
* @return current text in ip text field
*/
public String getText() {
StringBuffer buffer = new StringBuffer();
String ipResult;
for (int i = 0; i < textFields.length; i++) {
JTextField textField = textFields[i];
if(textField.getText().trim().equals("")){
return "";
}
buffer.append(Integer.parseInt(textField.getText()));
if (i < textFields.length - 1){
buffer.append('.');
}
}
ipResult = buffer.toString();
return ipResult;
}
/**
* general purpose key listener
*/
private class MyKeyListener implements KeyListener {
public void keyPressed(KeyEvent e) {
for (int i = 0; i < keyListenersList.size(); i++) {
KeyListener keyListener = keyListenersList.get(i);
keyListener.keyPressed(new KeyEvent(VersionTextField.this,
e.getID(), e.getWhen(), e.getModifiers(), e
.getKeyCode(), e.getKeyChar(), e
.getKeyLocation()));
}
}
public void keyReleased(KeyEvent e) {
for (int i = 0; i < keyListenersList.size(); i++) {
KeyListener keyListener = keyListenersList.get(i);
keyListener.keyReleased(new KeyEvent(VersionTextField.this, e
.getID(), e.getWhen(), e.getModifiers(),
e.getKeyCode(), e.getKeyChar(), e.getKeyLocation()));
}
}
public void keyTyped(KeyEvent e) {
for (int i = 0; i < keyListenersList.size(); i++) {
KeyListener keyListener = keyListenersList.get(i);
keyListener.keyTyped(new KeyEvent(VersionTextField.this, e.getID(),
e.getWhen(), e.getModifiers(), e.getKeyCode(), e
.getKeyChar(), e.getKeyLocation()));
}
}
}
private class MyFocusAdapter extends FocusAdapter {
public void focusGained(FocusEvent e) {
for (int i = 0; i < focusListenersList.size(); i++) {
FocusListener focusListener = focusListenersList.get(i);
focusListener.focusGained(new FocusEvent(
VersionTextField.this,
e.getID(),
e.isTemporary(),
e.getOppositeComponent()
));
}
if(e.getComponent() instanceof javax.swing.JTextField){
highlightText((JTextField)e.getSource());
}
}
public void focusLost(FocusEvent e) {
for (int i = 0; i < focusListenersList.size(); i++) {
FocusListener focusListener = focusListenersList.get(i);
focusListener.focusLost(new FocusEvent(
VersionTextField.this,
e.getID(),
e.isTemporary(),
e.getOppositeComponent()
));
}
}
public void highlightText(javax.swing.JTextField ctr){
//ctr.setSelectionColor(Color.BLUE);
//ctr.setSelectedTextColor(Color.WHITE);
ctr.setSelectionStart(0);
ctr.setSelectionEnd(ctr.getText().length());
System.out.println(ctr.getText());
}
}
}
here a view what we got:
here you go JFormattedTextField
精彩评论