简体   繁体   中英

using a mask in a jFormattedTextField in a javaBean Class

I Created a JFormattedTextField and using as a javaBean for multiple java Project, however, i didn't manage to figure out how use this field with a mask, the mask just doesn't work

Here's my class:

    package org.japo.java.swing.samples;

import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFormattedTextField;
import javax.swing.text.MaskFormatter;

/**
 *
 * @author ambro
 */
public class TextFieldCPF extends JFormattedTextField {

    public TextFieldCPF() {
    }
    
    public TextFieldCPF (String string){
        TextFieldCPF FormatoCPF = new TextFieldCPF("");
        try {
            MaskFormatter mask = new MaskFormatter("###");
            mask.install(FormatoCPF);
        } catch (ParseException ex) {
            Logger.getLogger(TextFieldCPF.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
}

I also tried to use a mask in this way:

try {
        MaskFormatter mask = new MaskFormatter("###");
        FormatoCPF = new JFormattedTextField(mask);
    } catch (ParseException ex) {
        Logger.getLogger(TextFieldCPF.class.getName()).log(Level.SEVERE, null, ex);
    }

So, how to mask a JFormattedTextField?

To improve what my question is:

I have this simple frame:

public class TestFrame extends javax.swing.JFrame {

public TestFrame() {
    initComponents();
    
}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    textFieldCPF1 = new org.japo.java.swing.samples.TextFieldCPF();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(117, 117, 117)
            .addComponent(textFieldCPF1, javax.swing.GroupLayout.PREFERRED_SIZE, 97, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(137, Short.MAX_VALUE))
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGap(79, 79, 79)
            .addComponent(textFieldCPF1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addContainerGap(90, Short.MAX_VALUE))
    );

    pack();
    setLocationRelativeTo(null);
}// </editor-fold>                        

/**
 * @param args the command line arguments
 */
public static void main(String args[]) {
    /* Set the Nimbus look and feel */
    //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
    /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
     * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
     */
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(TestFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    //</editor-fold>
    //</editor-fold>

    /* Create and display the form */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new TestFrame().setVisible(true);
            
        }
    });
}

// Variables declaration - do not modify                     
private org.japo.java.swing.samples.TextFieldCPF textFieldCPF1;
// End of variables declaration                   

}

What I want is to use the class TextFieldCPF in multiple java projects, not only in TestFrame

TextFieldCPF will have more than just the mask, afterwards i'll try to set other features and this field will be use as the pattern for other projects.

Your constructor public TextFieldCPF (String string){ is wrong. Don't create a new instance of the TextFieldCPF within the constructor, instead make use of the instance of the class which is been created (ie this ). Also, you shouldn't be consuming the exception, the caller needs to know when this fails.

public TextFieldCPF(String string) throws ParseException {
    MaskFormatter mask = new MaskFormatter(string);
    mask.install(this);
}

Having said that, the constructor is ambiguous, what is string ? Is it the text of field? Some kind of prompt? A tooltip?

Instead, you should make the parameter meaningful, in this case, ask for an instance of MaskFormatter , for example...

public TextFieldCPF(MaskFormatter mask) {
    mask.install(this);
}

or, alternatively, provide a factory method...

public static TextFieldCPF withMask(String mask) throws ParseException {
    TextFieldCPF field = new TextFieldCPF();
    MaskFormatter formatter = new MaskFormatter(mask);
    formatter.install(field);
    return field;
}

then code becomes more self documenting.

Talking of factories, since you're not actually adding any new functionality to the class, you should prefer composition over inheritance , instead, create and actual an factory class, for example...

public static class FormattedTextFieldFactory {
    public static JFormattedTextField withMask(String mask) throws ParseException {
        JFormattedTextField field = new JFormattedTextField();
        MaskFormatter formatter = new MaskFormatter(mask);
        formatter.install(field);
        return field;
    }
}

So, when I try to use public TextFieldCPF(MaskFormatter mask) { mask.install(this); } public TextFieldCPF(MaskFormatter mask) { mask.install(this); } I get this error: Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Uncompilable source code - constructor TextFieldCPF in class org.japo.java.swing.samples.TextFieldCPF cannot be applied to given types; required: javax.swing.text.MaskFormatter found: no arguments reason: actual and formal argument lists differ in length Exception in thread "AWT-EventQueue-0" java.lang.RuntimeException: Uncompilable source code - constructor TextFieldCPF in class org.japo.java.swing.samples.TextFieldCPF cannot be applied to given types; required: javax.swing.text.MaskFormatter found: no arguments reason: actual and formal argument lists differ in length

That's because you've not acutally implemented the public TextFieldCPF(MaskFormatter mask) { constructor - the error message is telling you every thing you need to know, for example...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.text.MaskFormatter;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (ParseException ex) {
                    ex.printStackTrace();;
                }
            }
        });
    }

    public class TextFieldCPF extends JFormattedTextField {
        public TextFieldCPF(String string) throws ParseException {
            MaskFormatter mask = new MaskFormatter(string);
            mask.install(this);
            setColumns(string.length());
        }
    }

    public class TestPane extends JPanel {
        public TestPane() throws ParseException {
            setLayout(new GridBagLayout());
            add(new TextFieldCPF("###"));
        }
    }
}

When I try public static TextFieldCPF withMask(String mask) throws ParseException { TextFieldCPF field = new TextFieldCPF(); MaskFormatter formatter = new MaskFormatter("###"); formatter.install(field); return field; } public static TextFieldCPF withMask(String mask) throws ParseException { TextFieldCPF field = new TextFieldCPF(); MaskFormatter formatter = new MaskFormatter("###"); formatter.install(field); return field; } public static TextFieldCPF withMask(String mask) throws ParseException { TextFieldCPF field = new TextFieldCPF(); MaskFormatter formatter = new MaskFormatter("###"); formatter.install(field); return field; } The mask does not work, just gives me a normal textfield

Works fine for me...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.text.MaskFormatter;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (ParseException ex) {
                    ex.printStackTrace();;
                }
            }
        });
    }

    public static class TextFieldCPF extends JFormattedTextField {
        public TextFieldCPF() {
        }

        public static TextFieldCPF withMask(String mask) throws ParseException {
            TextFieldCPF field = new TextFieldCPF();
            MaskFormatter formatter = new MaskFormatter(mask);
            formatter.install(field);
            field.setColumns(mask.length());
            return field;
        }
    }

    public class TestPane extends JPanel {
        public TestPane() throws ParseException {
            setLayout(new GridBagLayout());
            add(TextFieldCPF.withMask("###"));
        }
    }
}

And just to be sure, so does the factory...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.text.MaskFormatter;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (ParseException ex) {
                    ex.printStackTrace();;
                }
            }
        });
    }

    public static class FormattedTextFieldFactory {
        public static JFormattedTextField withMask(String mask) throws ParseException {
            JFormattedTextField field = new JFormattedTextField();
            field.setColumns(mask.length());
            MaskFormatter formatter = new MaskFormatter(mask);
            formatter.install(field);
            return field;
        }
    }

    public class TestPane extends JPanel {
        public TestPane() throws ParseException {
            setLayout(new GridBagLayout());
            add(FormattedTextFieldFactory.withMask("###"));
        }
    }
}

What I'm searching for is how to build a class to use in multiple projects Make a pattern of a JFormattedTextField with a mask, size and other features

My point remains the same, prefer composition over inheritance, you're not actually adding new functionality to the class, you're just "configuring" it, which might make a builder pattern more useful, for example...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.text.MaskFormatter;

public final class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    JFrame frame = new JFrame();
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (ParseException ex) {
                    ex.printStackTrace();;
                }
            }
        });
    }
    
    public class FormattedTextFieldBuilder {
        private JFormattedTextField textField;
        
        private String maskValue;
        private int columnCount = -1;
        private Object value;

        public FormattedTextFieldBuilder(JFormattedTextField textField) {
            this.textField = textField;
        }

        public FormattedTextFieldBuilder() {
            this(new JFormattedTextField());
        }
        
        public FormattedTextFieldBuilder withMask(String mask) {
            maskValue = mask;
            return this;
        }
        
        public FormattedTextFieldBuilder withColumnCount(int columnCount) throws ParseException {
            this.columnCount = columnCount > 0 ? columnCount : -1;
            return this;
        }
        
        public FormattedTextFieldBuilder withValue(Object value) throws ParseException {
            this.value = value;
            return this;
        }

        protected JFormattedTextField getTextField() {
            return textField;
        }

        protected String getMaskValue() {
            return maskValue;
        }
        
        protected MaskFormatter getMask() throws ParseException {
            String maskValue = getMaskValue();
            if (maskValue == null) {
                return null;
            }
            return new MaskFormatter(maskValue);

        }

        protected int getColumnCount() {
            return columnCount;
        }

        protected Object getValue() {
            return value;
        }
        
        public JFormattedTextField build() throws ParseException {
            JFormattedTextField textField = getTextField();
            MaskFormatter mask = getMask();
            int columnCount = getColumnCount();
            Object value = getValue();
            if (mask != null) {
                mask.install(textField);
            }
            if (columnCount > -1) {
                textField.setColumns(columnCount);
            }
            if (value != null) {
                textField.setValue(value);
            }
            return textField;
        }
    }

    public class TestPane extends JPanel {
        public TestPane() throws ParseException {
            setLayout(new GridBagLayout());
            
            JFormattedTextField textField = new FormattedTextFieldBuilder()
                    .withColumnCount(3)
                    .withMask("###")
                    .build();
            
            add(textField);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM