トップ 一覧 置換 検索 ヘルプ RSS ログイン

Swingコンポーネントで入力制限の変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
http://terai.xrea.jp/Swing/NumericTextField.html

!!方法1 入力制限機能付き JTextField
DocumentとInputVerifier を使って、長さチェック、パッディング、IM制御を
入れたTextFieldを実装する。
DocumentとInputVerifier、FocusListener を使って、
 ・長さチェック
 ・パッディング
 ・IM制御
の機能を持ったTextFieldを実装する。

{{code Java,
package tools.gui;

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import java.util.*;
import java.awt.event.*;

public class JTextFieldEx extends JTextField implements FocusListener {
  final public static int PADDING_NO = 0;
  final public static int PADDING_RIGHT = 1;
  final public static int PADDING_LEFT = 2;
  
  public static final int IM_NONE = 0;
  public static final int IM_HIRAGANA = 1;
  public static final int IM_HALFKANA = 2;
  public static final int IM_FULLASCII = 3;
  public static final int IM_OFF = 4;
  
  private static final Character.Subset[] SUBSET_OFF = null;
  private static final Character.Subset[] SUBSET_HIRAGANA  =  new Character.Subset[] {java.awt.im.InputSubset.KANJI};
  private static final Character.Subset[] SUBSET_HALFKANA = new Character.Subset[] {java.awt.im.InputSubset.HALFWIDTH_KATAKANA};
  private static final Character.Subset[] SUBSET_FULLASCII = new Character.Subset[] {java.awt.im.InputSubset.FULLWIDTH_LATIN};
  
  
  private int imType = IM_NONE;
  
  private int length;
  private int padType;
  private boolean blnPadEmpty;
  private LengthInputVerifier verifier;
  
  public JTextFieldEx() {
    this("");
  }
  
  public JTextFieldEx(String text) {
    this(text, 10, 256);
  }
  
  public JTextFieldEx(String text, int column, int length) {
    super(text, column);
    
    this.imType = IM_NONE;
    this.length = length;
    this.padType = PADDING_NO;
    this.blnPadEmpty = false;
    this.verifier = new LengthInputVerifier();
    
    
    this.setDocument(new LengthDocument());
    this.setInputVerifier(verifier);
    addFocusListener(this);
  }
  
  public void setPadding(char c, int padType) {
    this.padType = padType;
    verifier.setPadChar(c);
  }
  
  public void setPadding(char c) {
    setPadding(c, PADDING_LEFT);
  }
  
  public void setPaddingWhenEmpty(boolean blnPadEmpty) {
    this.blnPadEmpty = blnPadEmpty;
  }
  
  public int getLength() {
    return length;
  }
  
  public void setLength(int newValue) {
    this.length = newValue;
  }
  
  public int getImType() {
    return imType;
  }
  public void setImType(int newValue) {
    this.imType = newValue;
  }
  
  public void focusGained(FocusEvent e) {
    if (imType != IM_NONE) {
      Character.Subset[] subsets = SUBSET_OFF;
      switch (imType) {
      case IM_HIRAGANA:
        subsets = SUBSET_HIRAGANA;
        break;
      case IM_HALFKANA:
        subsets = SUBSET_HALFKANA;
        break;
      case IM_FULLASCII:
        subsets = SUBSET_FULLASCII;
        break;
      }
      getInputContext().setCharacterSubsets(subsets);
    }
  }
  
  public void focusLost(FocusEvent e) {
    if (imType != IM_NONE) {
      getInputContext().setCharacterSubsets(SUBSET_OFF);
    }
  }
  
  private class LengthDocument extends PlainDocument {
    public void insertString(int offs, String str, AttributeSet a)
    throws BadLocationException {
      if (getLength() >= length) {
        return;
      }
      super.insertString(offs, str, a);
    }
  }
  
  
  
  private class LengthInputVerifier extends InputVerifier {
    private char padChar;
    private String padString;
    
    public LengthInputVerifier() {
      setPadChar(' ');
    }
    
    private void createPadString() {
      char[] c = new char[length];
      Arrays.fill(c, padChar);
      padString = new String(c);
    }
    
    private void setPadChar(char padChar) {
      this.padChar = padChar;
      createPadString();
    }
    
    public boolean verify(JComponent c) {
      JTextComponent txtcomp = (JTextComponent)c;
      String inputtext = txtcomp.getText();
      int textlength = inputtext.length();
      
      // 空文字をパッディングしない場合
      if (!blnPadEmpty && textlength == 0) {
        return true;
      }
      if (textlength == length) {
        return true;
      }
      
      boolean verified = false;
      try {
        if (textlength > length) {
          txtcomp.setText(inputtext.substring(0, length));
        } else {
          if (padType == PADDING_LEFT) {
            inputtext = padString + inputtext;
            textlength = inputtext.length();
            txtcomp.setText(inputtext.substring(textlength - length));
          } else if (padType == PADDING_RIGHT) {
            inputtext = inputtext + padString;
            txtcomp.setText(inputtext.substring(0, length));
          }
        }
        verified = true;
      } catch (NumberFormatException e) {
        UIManager.getLookAndFeel().provideErrorFeedback(c);
        //Toolkit.getDefaultToolkit().beep();
      }
      // if (!verified){
      // JOptionPane.showMessageDialog(c,"エラーです");
      // }
      return verified;
    }
  }
}
}}

!!方法2 JTextField + InputVerifier 
方法1が大がかりで嫌な場合は、方法2、方法3を使う。

InputVerifierはコンポーネントを抜けるときにチェックされる。

{{code Java,
class IntegerInputVerifier extends InputVerifier{
  @Override
  public boolean verify(JComponent c) {
    boolean verified = false;
    JTextField textField = (JTextField)c;
    try{
      Integer.parseInt(textField.getText());
      verified = true;
    }catch(NumberFormatException e) {
      UIManager.getLookAndFeel().provideErrorFeedback(c);
      //Toolkit.getDefaultToolkit().beep();
    }
    return verified;
  }
}
}}

!!方法3 JTextField + Custom Document 
Document は入力中にチェックされる。

{{code Java,
class IntegerDocument extends PlainDocument {
  int currentValue = 0;
  public IntegerDocument() {
    super();
  }
  public int getValue() {
    return currentValue;
  }
  @Override
  public void insertString(int offset, String str, AttributeSet attributes)
        throws BadLocationException {
    if(str==null) {
      return;
    }else{
      String newValue;
      int length = getLength();
      if(length==0) {
        newValue = str;
      }else{
        String currentContent = getText(0, length);
        StringBuffer currentBuffer = new StringBuffer(currentContent);
        currentBuffer.insert(offset, str);
        newValue = currentBuffer.toString();
      }
      currentValue = checkInput(newValue, offset);
      super.insertString(offset, str, attributes);
    }
  }
  @Override
  public void remove(int offset, int length) throws BadLocationException {
    int currentLength = getLength();
    String currentContent = getText(0, currentLength);
    String before = currentContent.substring(0, offset);
    String after = currentContent.substring(length+offset, currentLength);
    String newValue = before + after;
    currentValue = checkInput(newValue, offset);
    super.remove(offset, length);
  }
  private int checkInput(String proposedValue, int offset) throws BadLocationException {
    if(proposedValue.length()>0) {
      try{
        int newValue = Integer.parseInt(proposedValue);
        return newValue;
      }catch(NumberFormatException e) {
        throw new BadLocationException(proposedValue, offset);
      }
    }else{
      return 0;
    }
  }
}}
{{category2 プログラミング言語,Java}}