javaswingfor-loopjtextfieldevent-dispatch-thread

Input from jtextfield doesnt get read while in a for loop


My problem is that I have a for loop and while this loop is running I still want inputs from JTextField to get read and not interrupt the loop or timing when the line gets printed.

public class test {

    public void Play() {

        JTextField textField = new JTextField();
        textField.addKeyListener(new KeyChecker());
        JFrame jframe = new JFrame();
        jframe.add(textField);
        jframe.setSize(200, 30);
        jframe.setVisible(true);
    }
}

class KeyChecker extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent event)
    {
        for(int i = 0; i < 1; i = 0)
        {
            char Input = event.getKeyChar();
            if(Input == 'a')
            {
                System.out.println("working");
            } else {
                System.out.println("not working");
            }
            try
            {
                Thread.sleep(1000);
            }
            catch(InterruptedException ex)
            {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Solution

  • In your code, the keyPressed method gets called by the Event Dispatch Thread (https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) every time you press a key in the textfield.

    In this context the KeyEvent event parameter represents a sing key press event, so it makes no sense to create a loop inside an event method, as maloomeister correctly pointed out.

    Instead you should perform your logic using the state of your classes, either KeyChecker or test. I don't really understand why you should regularly check for a key being pressed (and the purpose of a textfield BTW), anyway the following is a possible solution using a separate thread. Of course you can also do the loop in the main thread (which is not the EDT), but in a non-trivial application you should never do that.

    import java.awt.event.KeyEvent;
    
    import javax.swing.JFrame;
    import javax.swing.JTextField;
    
    public class Test {
        public static void main(String[] args) {
            KeyChecker keyChecker = new KeyChecker();
            JTextField textField = new JTextField(40);
            textField.addKeyListener(keyChecker);
            JFrame jframe = new JFrame();
            jframe.add(textField);
            jframe.pack();
            jframe.setVisible(true);
    
            Thread t = new Thread(() -> {
                while(true) {
                    char currentKey = keyChecker.getCurrentPressedKey();
                    switch (currentKey) {
                        case 'a':
                            System.out.println("working");
                            break;
                        default:
                            System.out.println("not working");
                    }
                        
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        break;
                    }
                }
            });
            
            t.start();
        }
    }
    
    class KeyChecker extends KeyAdapter {
        private char currentPressedKey = 0;
    
        @Override
        public void keyPressed(KeyEvent event) {
            currentPressedKey = event.getKeyChar();
        }
    
        @Override
        public void keyReleased(KeyEvent e) {
            currentPressedKey=0;
        }
        
        public char getCurrentPressedKey() {
            return currentPressedKey;
        }
    }