Search code examples
javanetbeansjtextfield

problems with focuslost in java


I have the following code that works correctly in my opinion but when I try to enter a new record starts blinking between charter field and the field name, this happens when the validation performed to see if the jtexfiedl is empty.

Here the code.

public void validarCedula(JTextField txt, JLabel lblMensaje) {
    texto = txt.getText().trim();
    tamanio = texto.length();
    lblMensaje.setText("");        
    try{
    if (texto.isEmpty()) 
    {
        lblMensaje.setText("Cedula Vacio");
        lblMensaje.setForeground(Color.red);
        txt.requestFocus();
    }
    else if (tamanio > 0 && tamanio < 9) {
        lblMensaje.setText("Cedula Incorrecta");
        lblMensaje.setForeground(Color.red);
        txt.requestFocus();
    } else if (tamanio == 10) {
        lblMensaje.setText("Cedula Correcta");
        lblMensaje.setForeground(Color.white);
    } else if (tamanio > 11 && tamanio < 13) {
        lblMensaje.setText("RUC Incorrecto");
        lblMensaje.setForeground(Color.red);
        txt.requestFocus();
    } else if (tamanio == 13) {
        lblMensaje.setText("R.U.C Correcto");
        lblMensaje.setForeground(Color.WHITE);
    }
    }catch(Exception ex)
    {
        JOptionPane.showMessageDialog(null, ex);
    }
}


public void validarNombre(JTextField txt, JLabel lblMensaje) {
    texto = txt.getText().trim();
    tamanio = texto.length();   
    try{
    if (texto.isEmpty()) 
    {
        lblMensaje.setText("Nombre Vacio");
        lblMensaje.setForeground(Color.red);
        txt.requestFocus();
    }
    else if (tamanio > 0 && tamanio < 7) {
            lblMensaje.setText("Debe Ingresar 2 Nombres");
            lblMensaje.setForeground(Color.red);
            txt.requestFocus();
        } else if (tamanio > 7 && tamanio < 24) {
            lblMensaje.setText("Nombre Correcto");
            lblMensaje.setForeground(Color.WHITE);
        } else if (tamanio > 25) {
            lblMensaje.setText("Nombre Incorrecto");
            lblMensaje.setForeground(Color.red);
            txt.requestFocus();
        }
    }catch(Exception ex)
    {
        JOptionPane.showMessageDialog(null, ex);
    }
}

These methods are called in the main class in each jtexfield focusLost event.

Someone could help me find the solution?


Solution

  • Your code locks up because it when one field loses focus, the other field gains focus. Your FocusListener tries to bring the focus back to the first field, but it can't because the second listener is trying to do the same, to bring the focus back to its field, resulting in the two validation methods continually being called, locking up your program.

    Add a two System.out.println(...) calls to prove this:

    public void validarCedula(JTextField txt, JLabel lblMensaje) {
        System.out.println("Dentro do validarCedula");  // ***** add this *****
        texto = txt.getText().trim();
    
        //...
    }
    
    
    public void validarNombre(JTextField txt, JLabel lblMensaje) {
       System.out.println("Dentro do validarNombre");  // ***** add this *****
    
       // ....
    }
    

    Solution: use an InputVerifier as noted in my comments.

    Code to test my assertion:

    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.event.FocusAdapter;
    import java.awt.event.FocusEvent;
    
    import javax.swing.*;
    
    public class Foo3b extends JPanel {
       private String texto;
       private int tamanio;
       private JTextField cedulaField = new JTextField(10);
       private JTextField nombreField = new JTextField(10);
       private JLabel mensajeLabel = new JLabel(" ");
    
       public Foo3b() {
          JPanel panel = new JPanel();
          panel.add(new JLabel("Cedula:"));
          panel.add(cedulaField);
          panel.add(new JLabel("Nombre:"));
          panel.add(nombreField);
    
          JPanel mensajePanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
          mensajePanel.add(new JLabel("Mensaje:"));
          mensajePanel.add(mensajeLabel);
    
          setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
          add(panel);
          add(mensajePanel);
    
          cedulaField.addFocusListener(new FocusAdapter() {
             @Override
             public void focusLost(FocusEvent e) {
                validarCedula(cedulaField, mensajeLabel);
             }
          });
    
          nombreField.addFocusListener(new FocusAdapter() {
             @Override
             public void focusLost(FocusEvent e) {
                validarNombre(nombreField, mensajeLabel);
             }
          });
       }
    
       public void validarCedula(JTextField txt, JLabel lblMensaje) {
          System.out.println("Dentro do validarCedula");
          texto = txt.getText().trim();
          tamanio = texto.length();
          lblMensaje.setText("");        
          try{
          if (texto.isEmpty()) 
          {
              lblMensaje.setText("Cedula Vacio");
              lblMensaje.setForeground(Color.red);
              txt.requestFocus();
          }
          else if (tamanio > 0 && tamanio < 9) {
              lblMensaje.setText("Cedula Incorrecta");
              lblMensaje.setForeground(Color.red);
              txt.requestFocus();
          } else if (tamanio == 10) {
              lblMensaje.setText("Cedula Correcta");
              lblMensaje.setForeground(Color.white);
          } else if (tamanio > 11 && tamanio < 13) {
              lblMensaje.setText("RUC Incorrecto");
              lblMensaje.setForeground(Color.red);
              txt.requestFocus();
          } else if (tamanio == 13) {
              lblMensaje.setText("R.U.C Correcto");
              lblMensaje.setForeground(Color.WHITE);
          }
          }catch(Exception ex)
          {
              JOptionPane.showMessageDialog(null, ex);
          }
      }
    
    
      public void validarNombre(JTextField txt, JLabel lblMensaje) {
         System.out.println("Dentro do validarNombre");
          texto = txt.getText().trim();
          tamanio = texto.length();   
          try{
          if (texto.isEmpty()) 
          {
              lblMensaje.setText("Nombre Vacio");
              lblMensaje.setForeground(Color.red);
              txt.requestFocus();
          }
          else if (tamanio > 0 && tamanio < 7) {
                  lblMensaje.setText("Debe Ingresar 2 Nombres");
                  lblMensaje.setForeground(Color.red);
                  txt.requestFocus();
              } else if (tamanio > 7 && tamanio < 24) {
                  lblMensaje.setText("Nombre Correcto");
                  lblMensaje.setForeground(Color.WHITE);
              } else if (tamanio > 25) {
                  lblMensaje.setText("Nombre Incorrecto");
                  lblMensaje.setForeground(Color.red);
                  txt.requestFocus();
              }
          }catch(Exception ex)
          {
              JOptionPane.showMessageDialog(null, ex);
          }
      }
    
      private static void createAndShowGui() {
         Foo3b mainPanel = new Foo3b();
    
         JFrame frame = new JFrame("Foo3");
         frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
         frame.getContentPane().add(mainPanel);
         frame.pack();
         frame.setLocationByPlatform(true);
         frame.setVisible(true);
      }
    
      public static void main(String[] args) {
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               createAndShowGui();
            }
         });
      }
    
    
    }
    

    Which returns:

    Dentro do validarCedula
    Dentro do validarNombre
    Dentro do validarCedula
    Dentro do validarNombre
    Dentro do validarCedula
    Dentro do validarNombre
    Dentro do validarCedula
    Dentro do validarNombre
    Dentro do validarCedula
    Dentro do validarNombre
    Dentro do validarCedula
    Dentro do validarNombre
    Dentro do validarCedula
    Dentro do validarNombre
    .
    .
    . 
    etc
    

    Better would be something like:

    import java.awt.Color;
    import java.awt.FlowLayout;
    import javax.swing.*;
    
    public class Foo3b extends JPanel {
       public static final int CEDULA_TAMANIO_CORRECTO1 = 10;
       public static final int CEDULA_TAMANIO_CORRECTO2 = 13;
       public static final Color COLOR_INCORRECTO = Color.RED;
       public static final Color COLOR_CORRECTO = Color.BLUE;
       public static final int NOMBRE_TAMANIO_MIN = 8;
       public static final int NOMBRE_TAMANIO_MAX = 24;
       private JTextField cedulaField = new JTextField(10);
       private JTextField nombreField = new JTextField(10);
       private JLabel mensajeLabel = new JLabel(" ");
    
       public Foo3b() {
          JPanel panel = new JPanel();
          panel.add(new JLabel("Cedula:"));
          panel.add(cedulaField);
          panel.add(new JLabel("Nombre:"));
          panel.add(nombreField);
    
          JPanel mensajePanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
          mensajePanel.add(new JLabel("Mensaje:"));
          mensajePanel.add(mensajeLabel);
    
          setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
          add(panel);
          add(mensajePanel);
    
          cedulaField.setInputVerifier(new CedulaVerifier());
    
          nombreField.setInputVerifier(new NombreVerifier());
       }
    
       private class CedulaVerifier extends InputVerifier {
          private String texto = "";
          private int tamanio = 0;
    
          @Override
          public boolean verify(JComponent input) {
             texto = ((JTextField) input).getText().trim();
             tamanio = texto.length();
    
             if (texto.isEmpty()) {
                return false;
             } else if (tamanio != CEDULA_TAMANIO_CORRECTO1
                   && tamanio != CEDULA_TAMANIO_CORRECTO2) {
                return false;
             }
             // default
             return true;
          }
    
          @Override
          public boolean shouldYieldFocus(JComponent input) {
             texto = ((JTextField) input).getText().trim();
             tamanio = texto.length();
             if (verify(input)) {
                mensajeLabel.setForeground(COLOR_CORRECTO);
                if (tamanio == CEDULA_TAMANIO_CORRECTO1) {
                   mensajeLabel.setText("Cedula Correcta");
                } else if (tamanio == CEDULA_TAMANIO_CORRECTO2) {
                   mensajeLabel.setText("R.U.C Correcto");
                }
    
                return true;
             } else {
                mensajeLabel.setForeground(COLOR_INCORRECTO);
    
                if (texto.isEmpty()) {
                   mensajeLabel.setText("Cedula Vacio");
                } else if (tamanio > 0 && tamanio < 9) {
                   mensajeLabel.setText("Cedula Incorrecta");
                } else if (tamanio > 11 && tamanio < 13) {
                   mensajeLabel.setText("RUC Incorrecto");
                } else if (tamanio > 13) {
                   mensajeLabel.setText("R.U.C INcorrecto");
                }
             }
             return false;
          }
    
       }
    
       private class NombreVerifier extends InputVerifier {
          private String texto = "";
          private int tamanio = 0;
    
          @Override
          public boolean verify(JComponent input) {
             texto = ((JTextField) input).getText().trim();
             tamanio = texto.length();
    
             if (texto.isEmpty()) {
                return false;
             } else if (tamanio < NOMBRE_TAMANIO_MIN
                   || tamanio > NOMBRE_TAMANIO_MAX) {
                return false;
             }
             // default
             return true;
    
          }
    
          @Override
          public boolean shouldYieldFocus(JComponent input) {
             texto = ((JTextField) input).getText().trim();
             tamanio = texto.length();
             if (verify(input)) {
                mensajeLabel.setForeground(COLOR_CORRECTO);
                mensajeLabel.setText("Nombre Correcto");            
                return true;
             } else {
                mensajeLabel.setForeground(COLOR_INCORRECTO);
                if (texto.isEmpty()) {
                   mensajeLabel.setText("Nombre Vacio");
                } else if (tamanio < NOMBRE_TAMANIO_MIN) {
                   mensajeLabel.setText("Debe Ingresar 2 Nombres");
                } else if (tamanio > NOMBRE_TAMANIO_MAX) {
                   mensajeLabel.setText("Nombre Incorrecto");
                }            
                return false;
             }
          }
       }
    
       private static void createAndShowGui() {
          Foo3b mainPanel = new Foo3b();
    
          JFrame frame = new JFrame("Foo3");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    
    }