1

I have a form that set a input verifier to it.

I want when a user type a correct value for a text field and want to go to other text field, a check icon should be display besides of text field. But now in my code, when user type a correct value on first text field an go to other, Two icons displayed together!

public class UserDialog extends JDialog {

JButton cancelBtn, okBtn;
JTextField fNameTf, lNameTf;
JRadioButton maleRb, femaleRb;
ButtonGroup group;
JLabel fNameLbl, fNamePicLbl, lNameLbl, lNamePicLbl, genderLbl, tempBtn, temp3;

    public UserDialog() {
    add(createForm(), BorderLayout.CENTER);
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setLocation(400, 100);
    pack();
    setVisible(true);
}
    public JPanel createForm() {
    JPanel panel = new JPanel();
    ImageIcon image = new ImageIcon("Check.png");

    okBtn = new JButton("Ok");
    cancelBtn = new JButton("Cancel");
    tempBtn = new JLabel();
    fNameLbl = new JLabel("First Name");
    fNamePicLbl = new JLabel(image);
    fNamePicLbl.setVisible(false);
    lNameLbl = new JLabel("Last Name");
    lNamePicLbl = new JLabel(image);
    lNamePicLbl.setVisible(false);
    genderLbl = new JLabel("Gender");

    maleRb = new JRadioButton("Male");
    femaleRb = new JRadioButton("Female");
    temp3 = new JLabel();
    group = new ButtonGroup();
    group.add(maleRb);
    group.add(femaleRb);

    fNameTf = new JTextField(10);
    fNameTf.setName("FnTF");
    fNameTf.setInputVerifier(new MyVerifier(new JComponent[]{maleRb, femaleRb, okBtn}));
    lNameTf = new JTextField(10);
    lNameTf.setName("LnTF");
    lNameTf.setInputVerifier(new MyVerifier(new JComponent[]{maleRb, femaleRb, okBtn}));

    panel.add(fNameLbl);
    panel.add(fNameTf);
    panel.add(fNamePicLbl);
    panel.add(lNameLbl);
    panel.add(lNameTf);
    panel.add(lNamePicLbl);
    panel.add(genderLbl);
    JPanel radioPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    radioPanel.add(maleRb);
    radioPanel.add(femaleRb);
    panel.add(radioPanel);
    panel.add(temp3);
    panel.add(okBtn);
    panel.add(cancelBtn);
    panel.add(tempBtn);

    panel.setLayout(new SpringLayout());
    SpringUtilities.makeCompactGrid(panel, 4, 3, 50, 10, 80, 60);
    return panel;
}
    public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            new UserDialog();
        }
    });
}

public class MyVerifier extends InputVerifier {
    private JComponent[] component;

    public MyVerifier(JComponent[] components) {
        component = components;
    }

    @Override
    public boolean verify(JComponent input) {
        String name = input.getName();

        if (name.equals("FnTF")) {
            String text = ((JTextField) input).getText().trim();
            if (text.matches(".*\\d.*") || text.length() == 0) {
                //disable dependent components
                for (JComponent r : component) {
                    r.setEnabled(false);
                }
                return false;
            }
        } else if (name.equals("LnTF")) {
            String text = ((JTextField) input).getText();
            if (text.matches(".*\\d.*") || text.length() == 0) {
                //disable dependent components
                for (JComponent r : component) {
                    r.setEnabled(false);
                }
                return false;
            }
        }
        //enable dependent components
        for (JComponent r : component) {
            r.setEnabled(true);
        }
        fNamePicLbl.setVisible(true);
        lNamePicLbl.setVisible(true);
        return true;
    }
}
}
}

Updated

 public class MyVerifier extends InputVerifier {
    private JComponent[] component;

    public MyVerifier(JComponent[] components) {
        component = components;
    }

    @Override
    public boolean verify(JComponent input) {
        String name = input.getName();

        if (name.equals("FnTF")) {
            String text = ((JTextField) input).getText().trim();
            if (text.matches(".*\\d.*") || text.length() == 0) {
                return false;
            }
        } else if (name.equals("LnTF")) {
            String text = ((JTextField) input).getText();
            if (text.matches(".*\\d.*") || text.length() == 0) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean shouldYieldFocus(JComponent input) {
        boolean isValidDate = verify(input);
        if (isValidDate) {
            for (JComponent r : component) {
                r.setEnabled(true);
            }
        } else {
            for (JComponent r : component) {
                r.setEnabled(false);
            }
        }
        return isValidDate;
    }
Sajad
  • 2,273
  • 11
  • 49
  • 92

1 Answers1

3

But now in my code, when user type a correct value on first text field an go to other, Two icons displayed together!

Because you did so: (Read the comments)

public boolean verify(JComponent input) {
        String name = input.getName();

        if (name.equals("FnTF")) {
            // your code
            }
        } else if (name.equals("LnTF")) {
            // your code

        }
        //enable dependent components
        for (JComponent r : component) {
            r.setEnabled(true);
        }
        /* And Now we are here */
        fNamePicLbl.setVisible(true); 
        lNamePicLbl.setVisible(true);
         // making visible two of them at once as soon as verify is called 
            // on any one of the components, verifier is registered

        return true;
    }

setVisible should be controlled by the if-else condition too. For your better understanding you need to do something like this:

      if (text.matches(".*\\d.*") || text.length() == 0) {
           // your code
        }
        else
        {
            fNamePicLbl.setVisible(true);

        } 

Second Issue:

    fNameTf.setInputVerifier(new MyVerifier(new JComponent[]{maleRb, femaleRb, okBtn}));
    lNameTf = new JTextField(10);
    lNameTf.setName("LnTF");
    lNameTf.setInputVerifier(new MyVerifier(new JComponent[]{maleRb, femaleRb, okBtn}));

The MyVerfier has the common code to verify both input field. But you are creating two instances of it with same instances of components. Create one and set it as the input verifier of the two field.

You might want to create two different InputVerifier class for the two Text Field. FnTFVerifier and LnTFVerifier. Then put your verification code that relates them e.g., enabling the radio buttons and showing the label with check.png. most of the if-else checking will go-away.

But I think, this should not really be the preferable way. As the two text field has the common functionality, one InputVerifier class and instance is sufficient. you would have to just encapsulate the input text field and related cehckLabel to one component, then register the InputVerifier instances to this component.

Third issue: you are misusing verify function:

The verify function is meant to be used for nothing but verify data: whether data is valid or not with user required condition. It should do nothing more. InputVerifier has another function boolean ShouldYieldFocus(Jcomponent): Before focus is transfered to another Swing component that requests it, the input verifier's shouldYieldFocus method is called, which decides whither the component under verification should lose focus or not. Focus is transferred only if this method returns true. You should however write the required state change of components inside this function.

public boolean shouldYieldFocus(JComponent input) {
    boolean isDataValid =  verify(input);

    if(isDataValid); //do stuff

    return isDataValid; // if verify is true(valid) return true;
 }
Sage
  • 15,290
  • 3
  • 33
  • 38
  • So in order your answer, Can i show that icon with `shouldYieldFocus(...)`? – Sajad Oct 22 '13 at 15:28
  • 1
    :) you can show it with your current code too. i have indicated a conditional code fragment to help you with. Inside your if-else conditional check of `"FnTf"(or "LnTF")` text. When if `(text.matches(".*\\d.*") || text.length() == 0)` condition is false for `FnTF` show `fNamePicLabel` and when the same condition is false for `LnTF`, show `lNamePicLabel` with `setVisible(true)`. First get it working then try the same example with `shouldYeildFocus` function. – Sage Oct 22 '13 at 15:42
  • I do it by if-else conditional, now i want to use `shouldYieldFocus(...)`, See update please. – Sajad Oct 22 '13 at 16:42
  • @Sajjad, Hint for you: your verification was: this condition: `(text.matches(".*\\d.*") || text.length() == 0)` right? if this condition returns true than you disable components and if it false than you enable components including showing the checkmark. Put your verification condition in verify function. Put Rest of the handling inside your shouldYieldFocus function. Do it first – Sage Oct 22 '13 at 17:03
  • As you say, I put verify condition on `verify` method, and put enable/disabling function on `shouldYieldFocus` method. See update. – Sajad Oct 25 '13 at 18:29
  • Thanks. Now It looks much nicer. – Sage Oct 25 '13 at 20:59