Logo VB-EDV-Beratung

VbIntField

Die Klasse VbIntField ist eine Erweiterung der Klasse JTextField, die ganze Zahlen einliest. Dabei können die Stellenanzahl und andere Eigenschaften vorgegeben werden. Als zusätzliche Informationen werden
len die Länge des Feldes
maxSep die maximale Anzahl Tausender-Trennzeichen
zero ob auf im Feld führende Nullen dargestellt werden sollen
thousandSeperator ob im Feld Tausender-Trennzeichen dargestellt werden sollen
df das DecimalFormat für die Darstellung
chSep das Tausender-Trennzeichen
gespeichert.

package vb;

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

public class VbIntField extends JTextField implements FocusListener {
    int len = 0, maxSep = 0;
    boolean zero = false,
    thousandSeparator = true;
    DecimalFormat df = new DecimalFormat();
    char  chSep = '.';

Den verschiedenen Konstruktoren kann man einige Eigenschaften gleich mitgeben.

    public VbIntField() {
        setup();
    }

    public VbIntField(int cols) {
        len = cols;
        setup();
    }

    public VbIntField(int val, int cols) {
        len = cols;
        setup();
        setInt(val);
    }

    public VbIntField(int cols, boolean sep) {
        len = cols;
        thousandSeparator = sep;
        setup();
    }

    public VbIntField(int cols, boolean sep, boolean zr) {
        len = cols;
        thousandSeparator = sep;
        zero = zr;
        setup();
    }

    public VbIntField(int val, int cols, boolean sep) {
        len = cols;
        thousandSeparator = sep;
        setup();
        setInt(val);
    }

    public VbIntField(int val, int cols, boolean sep, boolean zr) {
        len = cols;
        thousandSeparator = sep;
        zero = zr;
        setup();
        setInt(val);
    }

setup() und setupDf() machen die Initialisierung bzw. Änderungen.

    void setup(){
        setHorizontalAlignment(JTextField.RIGHT);
        addFocusListener(this);
        setupDf();
    }

    void setupDf(){
        StringBuffer bf = new StringBuffer(100);
        char digit = zero ? '0' : '#';
        int i;
        if (len < 1)
            len = 10;
        DecimalFormatSymbols fs = new DecimalFormatSymbols();
        chSep = fs.getGroupingSeparator();
        if (thousandSeparator){
            maxSep = (len-1)/3;
            for (i=0;i<len-3;i++)
                bf.append(digit);
            bf.append(',');
            bf.append(digit);
            bf.append(digit);
            bf.append('0');
        } else {
            maxSep = 0;
            for (i=0;i<len-1;i++)
                bf.append(digit);
            bf.append('0');
        }
        int width0 = getFontMetrics(getFont()).charWidth('0'),
            widthSep = getFontMetrics(getFont()).charWidth(chSep);
        Dimension d = getPreferredSize();
        d.width = len * width0 + maxSep * widthSep + 6;
        setPreferredSize(d);
        df = new DecimalFormat(bf.toString());
    }

Diese Methoden verändern einzelne Eigenschaften.

    public void setZeroes(boolean zr){
        zero = zr;
        setupDf();
    }

    public void setThousandSeparator(boolean th){
        thousandSeparator = th;
        setupDf();
    }

setInt(int val) setzt den Text des Feldes auf den Wert von val.

    public void setInt(int val){
        setText(df.format(val));
    }

getInt() gibt den numerischen Wert des Feldes zurück und löst gegebenenfalls eine VbDialogException aus.

    public int getInt() throws VbDialogException{
        int ret = 0;
        try {
            ret = df.parse(getText()).intValue();
        } catch (ParseException pe) {
            throw new VbDialogException(this,"falscher Wert '" + getText() + "'");
        }
        return ret;
    }

Wenn das Feld den Fokus verliert, soll der Inhalt ordentlich formatiert werden. focusGained ist nur da, damit das Interface FocusListener vollständig ist.

    public void focusLost(FocusEvent fe){
        if (!fe.isTemporary()) {
            try {
                setInt(getInt());
            } catch (VbDialogException vde) {
                Toolkit.getDefaultToolkit().beep();
            }
        }
    }

    public void focusGained(FocusEvent fe){
    }

Damit nur Ziffern und nur bis zur maximalen Länge eingegeben werden können, wird einfach als Dokumenten-Model ein eingeschränktes PlainDocument verwendet.

    protected class VbIntFieldDocument extends PlainDocument {
        public void insertString(int offs, String str, AttributeSet a)
            throws BadLocationException {
            if (str == null)
                return;
            int nSep = 0, nDig = 0, i;
            char[] source = str.toCharArray(),
                   result = new char[source.length],
                   contents = getText(0,getLength()).toCharArray();

            for (i=0;i<contents.length;i++){
                if (contents[i] == chSep)
                    nSep++;
                else
                    nDig++;
            }
            int j = 0;
            int maxLen = (len + maxSep) - getLength();
            for (i=0; i<source.length; i++) {
                if ((Character.isDigit(source[i]) && (nDig++ < len)) ||
                    ((source[i] == chSep) && (nSep++ < maxSep)))
                    result[j++] = source[i];
                else {
                    Toolkit.getDefaultToolkit().beep();
                }
            }
            super.insertString(offs, new String(result, 0, j), a);
        }
    }

    protected Document createDefaultModel() {
        return new VbIntFieldDocument();
    }

Und hier gibt's VbIntField.java noch mal im Stück.

© 2003 Volker Böhm Best viewed with any Browser Valid HTML 4.0