0

I have an InputVerifier on a JFormattedTextField. It is called when field looses focus perfectly. I added a cancel button (JButton), but do not want to call then InputVerifier when this button is clicked.

MyVerifier is called when the focus is lost on the field without any problem. However, after I click the clearButton the InputVerifier won´t be called again, as if the button where clicked even if it´s not.

The complete code is:

public class DemoFrame extends javax.swing.JFrame {

    /** Creates new form DemoFrame */
    public DemoFrame() {
        initComponents();
        name.setValue("");
        name.setInputVerifier(new MyVerifier());
        clear.setVerifyInputWhenFocusTarget(false);
    }

    private class MyVerifier extends javax.swing.InputVerifier {
     public boolean verify(javax.swing.JComponent input) {
         System.out.println("Field is being verified");
          return true;
      }
      public boolean shouldYieldFocus(javax.swing.JComponent input) {
          return verify(input);
      }
  }

    /** 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() {

        name = new javax.swing.JFormattedTextField();
        clear = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        name.setText(" ");

        clear.setText("clear");
        clear.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(231, Short.MAX_VALUE)
                .addComponent(clear)
                .addGap(112, 112, 112))
            .addGroup(layout.createSequentialGroup()
                .addGap(116, 116, 116)
                .addComponent(name, javax.swing.GroupLayout.PREFERRED_SIZE, 128, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(156, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGap(94, 94, 94)
                .addComponent(name, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 90, Short.MAX_VALUE)
                .addComponent(clear)
                .addGap(73, 73, 73))
        );

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

    private void clearActionPerformed(java.awt.event.ActionEvent evt) {
        name.setValue(null);
    }

    /**
     * @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(DemoFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(DemoFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(DemoFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(DemoFrame.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 DemoFrame().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify
    private javax.swing.JButton clear;
    private javax.swing.JFormattedTextField name;
    // End of variables declaration
}

Why isn't the InputVerifier been invoked if the field looses focus without the button being clicked?

camickr
  • 321,443
  • 19
  • 166
  • 288
AlbertoLopez
  • 101
  • 3
  • 1
    Post an [mcve] that demonstrates the problem. Your "Clear" button must execute some code that is causing a problem. – camickr Nov 08 '17 at 18:38
  • ok, I included the whole code. – AlbertoLopez Nov 08 '17 at 18:54
  • If I add another JFormattedTextField between the Verified field and the JButton the problem disappears. I suppose the verified field isn´t being verified because the button gains focus. I guess the work around is to include a focusable dummy field. Is there a better solution? – AlbertoLopez Nov 08 '17 at 19:11
  • As far as I can see, the `InputVerifier` isn't been called because you told the API not to call it, but setting `setVerifyInputWhenFocusTarget` to `false`. This means that when the field has focus and then focus is moved to the `clear` button, `InputVerifier` is simply not called – MadProgrammer Nov 08 '17 at 19:24
  • I suppose I should change the question to, how do I avoid a field from being verified when the focus is lost by clicking on a button such as a cancel button? – AlbertoLopez Nov 08 '17 at 19:48

1 Answers1

0

Well. I found the solution.

    clear.setFocusable(false);

That solves the problem.

AlbertoLopez
  • 101
  • 3
  • That's not a very good solution, since now the user can't navigate to the button via the keyboard – MadProgrammer Nov 08 '17 at 19:20
  • perhaps. But why navigate to a cancel button? The user will be able to navigate to other fields or components except the cancel button. That doesn´t seem unreasonable. Also, can´t come with another simple solution. – AlbertoLopez Nov 08 '17 at 19:25
  • For users who rely on screen readers, this is a problem, as they won't navigate with the mouse, they navigate with the keyboard. Advance users often don't use the mouse, they navigate with the keyboard. I know it would annoy the crap out of me. Personally, I don't like the `InputVerifier` when it restricts the focus, as it's perfectly reasonable for a user to enter values in a way in which defies the order displayed, instead, know, they have to change the way they think and focus on the order the developer decided, I prefer a combination of marking fields visually and post validation – MadProgrammer Nov 08 '17 at 19:28
  • I understand and agree. However, the field I need to verify is a dababase key. So if the user changes this field I need to reload the whole form. So it is critic to verify user input on it. I could add a propertyChangeListener, but then I won´t know if the user changed the value or the application (for example when the button clears the form). – AlbertoLopez Nov 08 '17 at 19:34
  • So... the thing that jumps up and slaps me about the face is ... where's the "Ok" or "Accept" button? The basic problem you've presented is that there are only two components, which doesn't entirely make sense, since they have the ability to "dismiss" the value, how do they "accept" it? A third component would solve the issue – MadProgrammer Nov 08 '17 at 19:56
  • the form has an accept button, plus other fields. I didn´t inlude them in order to make the source code smaller. However, if the "cancel button" is focusable, then if the user changes the field value (the one I want to verify) when the cancel button has focus, the field won´t be verified. And that will be trouble in my application. – AlbertoLopez Nov 08 '17 at 20:36
  • So, I'd include both a form of active and passive validation, so you can validate the form as the user input values, but you should also validate the form when the submit it - because they might skip fields altogether - just as a general recommendation ;) – MadProgrammer Nov 08 '17 at 20:44