1

I have 2 JTextFields:

JTextField txtJobType, txtPriorityCode;

This is the functionality I need:

When user types in 'administration' in txtJobType and hits tab (or clicks away) an error check is done to see whether the field is empty or if the text entered exists in database. The way I have done that is:

private void txtJobTypeFocusLost(java.awt.event.FocusEvent evt) {                                     
    System.out.println("JobType Focus Lost");
    if (!checkFieldExists(txtJobType.getText(), "jobType", "jobCode",
            JobType.class) || txtJobType.getText().isEmpty()) {
        txtJobType.requestFocusInWindow();
        txtJobType.selectAll();
    } else {
    }
} 

So if the field doesn't exist or the text is empty, then return focus to the txtJobType and highlight all the text (if any)

That works without a problem. However, I have the txtPriorityCode field which needs to have the exact same behaviour. So I did:

private void txtPriorityCodeFocusLost(java.awt.event.FocusEvent evt) {                                          
    System.out.println("PriorityCode Focus Lost");
    if (!checkFieldExists(txtPriorityCode.getText(), "priority", "priorityCode",
            Priority.class) || txtPriorityCode.getText().isEmpty()) {
        txtPriorityCode.requestFocusInWindow();
        txtPriorityCode.selectAll();
    }
}

This is where the problem starts: if user leaves jobType and tabs to Priority then the code attempts to return focus back to jobtype, but because priority is also blank at that point, it will attempt to get focus back from jobtype, resulting in this output:

PriorityCode Focus Lost
JobType Focus Lost
PriorityCode Focus Lost
JobType Focus Lost

Any help on how I could implement this behaviour is appreciated, as I have to do this for at least 10 other textfields.

Thank You!

kleopatra
  • 51,061
  • 28
  • 99
  • 211
Metal Wing
  • 525
  • 1
  • 11
  • 22

3 Answers3

5

You shouldn't be fiddling with focus lost or other low-level constructs. Instead, why not simply use an InputVerifier as per this example and this one too?

For example, it could look something like this:

import javax.swing.*;

public class InputVerifierEg {
   private JPanel mainPanel = new JPanel();
   private JTextField txtJobType = new JTextField(10);
   private JTextField txtPriorityCode = new JTextField(10);

   public InputVerifierEg() {
      txtJobType.setInputVerifier(new MyInputVerifier("jobType", "jobCode",
            JobType.class));
      txtPriorityCode.setInputVerifier(new MyInputVerifier("priority", "priorityCode",
            Priority.class));

      mainPanel.add(new JLabel("Job Type:"));
      mainPanel.add(txtJobType);
      mainPanel.add(Box.createHorizontalStrut(15));
      mainPanel.add(new JLabel("Priority Code:"));
      mainPanel.add(txtPriorityCode);

   }

   public JPanel getMainPanel() {
      return mainPanel;
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("InputVerifierEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new InputVerifierEg().getMainPanel());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

class MyInputVerifier extends InputVerifier {
   private String fieldName;
   private String codeName;
   private Class<?> classType;

   public MyInputVerifier(String fieldName, String codeName, Class<?> classType) {
      this.fieldName = fieldName;
      this.codeName = codeName;
      this.classType = classType;
   }

   @Override
   public boolean verify(JComponent input) {
      JTextField tField = (JTextField) input;

      // assuming that the checkFieldExists is a static method of a utility class
      if (!FieldCheckerUtil.checkFieldExists(tField.getText(), fieldName,
            codeName, classType)) {
         return false;
      }

      if (tField.getText().trim().isEmpty()) {
         return false;
      }
      return true;
   }

   @Override
   public boolean shouldYieldFocus(JComponent input) {
      JTextField tField = (JTextField) input;

      if (verify(input)) {
         return true;
      } else {
         tField.selectAll();
         // show JOptionPane error message?
         return false;
      }
   }
}
Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • @kleo: we must have been typing in at the same time. – Hovercraft Full Of Eels Aug 21 '12 at 16:11
  • That is great and works exactly how I need it to, except for one thing: how would I implement the check to see whether the text entered is present in the database? Each textfield is associated with a different entity, so in my focusLost method you can see me passing the Entity class and table names. I don't quite see how I could implement that into the MyInputVerifier if-statement. – Metal Wing Aug 21 '12 at 16:29
  • @MetalWing: I don't see this as an issue. You could pass the same information in your verifier's constructor or use a HashMap to hold this information. – Hovercraft Full Of Eels Aug 21 '12 at 16:42
  • @HovercraftFullOfEels as stupid as it sounds, is there a chance you could demonstrate me the concept? I can see that `public boolean verify(JComponent input) {` is where I would make it `public boolean verify(JComponent input , String tableField, Class entityClass)` but how do I pass different class for each textfield in the constructor? – Metal Wing Aug 21 '12 at 17:34
  • @Metal: but note that your passing a class type into a method parameter gives the code a bad smell. I suspect the code would be much cleaner if you used generics instead. – Hovercraft Full Of Eels Aug 22 '12 at 02:05
0

Maybe do one check of:

txtPriorityCode.getText().isEmpty()

And then on the other, test if:

!txtPriorityCode.getText().isEmpty() && txtJobType.getText().isEmpty()

i.e. only do the check on the second one if the first one isn't empty.

mguymon
  • 8,946
  • 2
  • 39
  • 61
0

Personally, I hate it when validation is done like this and prevents me from moving around fields in a form as I see fit. Why not do validation on all the fields when the form is submitted and highlight the invalid ones at that time?

sdoca
  • 7,832
  • 23
  • 70
  • 127
  • I haven't worked with swing for some time, but is it possible to have one focusLost method that internally checks which field lost focus and returns focus to that field when validation fails? – sdoca Aug 21 '12 at 16:08