javaeclipseuser-interfacejtextfield

How to rectify "over-sensitive" JTextField input issue


I've just come over to JAVA from BASIC, so please forgive me for any convention issues with my coding.

I have a mildly infuritating GUI-related issue. I have constructed a matrix-multiplication calculator which does calculations on inputted letters (using MOD 26). I run the program exclusively on Eclipse and have included a picture of the actual program in operation below...

The issue is with the Jtextfield boxes which take the inputted letters:

Actual program running on Eclipse

Basically, I wanted to be able to input a letter in a box, then to have the cursor move to the next box (cycling back to the first box after all the letters are inputted). I used a 'KeyListener' as shown in the code for the first JTextField 'letter box':

  A_RUCE = new JTextField(2);
  A_RUCE.setFont(new Font("Serif", Font.PLAIN, 18));
  A_RUCE.setEditable(true);
  cp.add(A_RUCE);
  A_RUCE.setText("");
  
  A_RUCE.addKeyListener(new KeyAdapter(){
      public void keyPressed(KeyEvent e){
      String value=A_RUCE.getText();
      if(value.length()==0){
          B_RUCE.requestFocus();
      }
    }
  }); 

The problem is that when I run the program, most of the time, the thing becomes "over sensitive". I try to input a letter and the cursor skips a box. I consider key repeating rate on my computer and such, and have adjusted settings, but this did not help.

All I am seeking is for when a letter is inputted, that the cursor moves to the next box without it 'skipping' over a box. I don't know why that happens, and I cannot figure out an alternative way to fix the issue. I would be very grateful if someone could help with this. Thank you kindly.


Solution

  • I'd be more inclined to use a DocumentListener. You can check the length of the text and then move onto the next field. This is the sort of thing you could do:

    import java.awt.Component;
    import java.awt.Container;
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JFrame;
    import javax.swing.JTextField;
    import javax.swing.JButton;
    import javax.swing.JPanel;
    import java.awt.EventQueue;
    import javax.swing.event.DocumentListener;
    import javax.swing.event.DocumentEvent;
    
    public class FB extends JFrame implements DocumentListener {
        private JTextField[] fields = new JTextField[3];
    
        public void insertUpdate(DocumentEvent e) {
            int textLen = e.getDocument().getLength();
            if (textLen == 1) {
                // focus next
                int nextToFocus = 0;
                Component c = getFocusOwner();
                for (int i = 0; i < fields.length; i++) {
                    if (fields[i] == c) {
                        nextToFocus = i + 1;
                        break;
                    }
                }
                nextToFocus %= fields.length;
                System.out.printf("Next to focus is field %d%n", nextToFocus);
                fields[nextToFocus].requestFocus();
            }
        }
    
        public void removeUpdate(DocumentEvent e) {
        } // No-op
    
        public void changedUpdate(DocumentEvent e) {
            // No-op
        }
    
        private void setGui() {
            try {
                setLocation(0, 100);
                setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
                Container cp = getContentPane();
                JPanel fieldsPanel = new JPanel();
                for (int i = 0; i < fields.length; i++) {
                    JTextField tf = new JTextField(1);
                    tf.getDocument().addDocumentListener(this);
                    fieldsPanel.add(tf);
                    fields[i] = tf;
                }
                setContentPane(fieldsPanel);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            try {
                EventQueue.invokeAndWait(() -> {
                    FB f = new FB();
                    f.setGui();
                    f.setSize(200, 200);
                    f.setVisible(true);
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }