How to create a mask for JformattedTextField?

4

I'm doing a program that simulates the Turing Machine, and the user fills a form with the states like this {q0,q1,q2} .

But I want to create a mask that the user types only q0q1q2 and the value is thus formatted {q0,q1} and allows you to type one or more states ex: {q0} or {q0,q1,q2} .

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package MaquinaTuring;

public class Maquina extends javax.swing.JFrame {

    /**
     * Creates new form Maquina
     */
    public Maquina() {
        initComponents();
    }

    String entrada;
    String [] estados;

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jFormattedTextField1 = new javax.swing.JFormattedTextField();
        jButton1 = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jLabel1.setFont(new java.awt.Font("Tahoma", 0, 18)); // NOI18N
        jLabel1.setText("Máquina de Turing");

        jLabel2.setText("Informe os Estados (Q):");

        try {
            jFormattedTextField1.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.MaskFormatter("{#,#}")));
        } catch (java.text.ParseException ex) {
            ex.printStackTrace();
        }

        jButton1.setText("Verificar");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(119, 119, 119)
                        .addComponent(jLabel1))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(27, 27, 27)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel2)
                            .addComponent(jFormattedTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 134, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(157, 157, 157)
                        .addComponent(jButton1)))
                .addContainerGap(133, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(34, 34, 34)
                .addComponent(jLabel1)
                .addGap(23, 23, 23)
                .addComponent(jLabel2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jFormattedTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 58, Short.MAX_VALUE)
                .addComponent(jButton1)
                .addGap(95, 95, 95))
        );

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

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         

        entrada = jFormattedTextField1.getText();
        estados = entrada.split(",");

        if (estados[0].isEmpty() == false) {
            estados[0] = estados[0].replace("{", "");
            estados[estados.length - 1] = estados[estados.length - 1].replace("}", "");
        }

        for (int i = 0; i < estados.length; i++) {
            System.out.println("Estados " + i + " :"+ estados[i]);
        }
    }                                        

    /**
     * @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(Maquina.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Maquina.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Maquina.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Maquina.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

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

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JFormattedTextField jFormattedTextField1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    // End of variables declaration                   
}
    
asked by anonymous 01.10.2017 / 00:42

1 answer

2

One way I have been able to do this is by applying regular expression to what is typed in a JTextField , so that only the states that are valid ( {q0,q1,q2,q3,...q10} ) in the qXX format are rescued, removing all the rest. Each time the button is pressed, it will format the states by entering commas between them and two keys ( {} ) at the beginning and at the end.

See the example:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

public class Maquina3 extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private JPanel panelNorth;
    private JTextField textField;
    private JPanel panelSouth;
    private JButton btnFormatar;

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new Maquina3().setVisible(true);
        });
    }

    public Maquina3() {
        initComponents();
        pack();
        setLocationRelativeTo(null);
    }

    private void initComponents() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(400, 250));
        this.contentPane = new JPanel(new BorderLayout(0, 0));
        this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(this.contentPane);

        this.panelNorth = new JPanel();
        this.contentPane.add(this.panelNorth, BorderLayout.NORTH);

        this.panelSouth = new JPanel();
        this.contentPane.add(this.panelSouth, BorderLayout.SOUTH);

        this.textField = new JTextField();
        this.textField.setColumns(15);
        this.panelNorth.add(this.textField);

        this.btnFormatar = new JButton("Formatar");
        btnFormatar.addActionListener(e -> {

            String text = textField.getText();

            if (text == null | text.length() == 0)
                return;

            String regex = "([Qq]{1}(0[1-9]|10))";
            StringBuilder builder =  new StringBuilder();

            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(text);

            while (m.find()) {

                builder.append(builder.length() == 0 ? "" : ",");
                builder.append(m.group());
            }
            builder.insert(0, "{");
            builder.append("}");

            textField.setText(builder.toString().toLowerCase());
        });

        this.panelSouth.add(this.btnFormatar);
    }
}

The regex ([Qq]{1}(0[1-9]|10)) will validate only those parts of the text that are in the qXX format where XX is between 01 and 10. Then in while , I am concatenating all found states and separating them with a comma. The ternary condition is so that the comma is only added if the builder is not empty, so there will not be a comma left in the beginning as was occurring at previous issue of this answer.

Finally, I added the keys at the beginning and end of the builder and converted it to String by displaying it in the field, converting it to the lower case.

See working:

    
01.10.2017 / 16:36