0

I am writing a command line application in Java. Rather than using System.console(), I am writing a custom console, that will run within a JFrame. This is primarily to circumvent the fact that System.console() returns null from within an IDE like eclipse.

I only require the console to have very basic features:

  • Backspace and Delete keys must remove the character behind or in front of the Caret
  • Up and Down keys must cycle through previously typed commands.

I have achieved this by using a KeyEventListener, and using a switch statement to select the appropriate action for the special keys (Backspace, Delete, Up, Down, Left, Right etc.) and otherwise printing the pressed key to the console.

Everything works, except when the Delete key is pressed, both the Delete and Up statements within the switch statement are executed. This implies that pressing the delete key fires both a Delete event, and then an Up event separately. When pressing the Delete key, the character immediately in front of the Caret is deleted, and then the previously entered command is displayed.

public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()){
            case KeyEvent.VK_ENTER: 
                String line = getLine();
                previousCommands.add(line.substring(1));
                output.append("\n" + line);
                commandPosition = 0;
                setFinished(true);
                break;

            case KeyEvent.VK_BACK_SPACE:
                if(input.getCaretPosition() <= 1){
                    break;
                }
                int caretPosition = input.getCaretPosition();
                String text = input.getText().
                        substring(0, input.getCaretPosition() - 1) +
                        input.getText().
                        substring(input.getCaretPosition());
                input.setText(text);
                input.setCaretPosition(caretPosition -1);
                break;

            case KeyEvent.VK_DELETE:
                if(input.getCaretPosition() == input.getText().length()){
                    break;
                }
                int otherCaretPosition = input.getCaretPosition();
                String otherText = input.getText().
                        substring(0, otherCaretPosition) +
                        input.getText().
                        substring(otherCaretPosition + 1);
                input.setText(otherText);
                input.setCaretPosition(otherCaretPosition);
                            break;

            case KeyEvent.VK_UP:
                if(previousCommand() != null){
                    setLine(">" + previousCommand());
                }
                break;

            case KeyEvent.VK_DOWN:
                if(nextCommand() != null){
                    setLine(">" + nextCommand());
                }
                break;

            case KeyEvent.VK_LEFT:
                if(input.getCaretPosition() <= 1){
                    input.setCaretPosition(1);
                    break;
                }
                input.setCaretPosition(input.getCaretPosition() - 1);
                break;

            case KeyEvent.VK_RIGHT:
                if(input.getCaretPosition() == input.getText().length()){
                    input.setCaretPosition(input.getText().length());
                    break;
                }
                input.setCaretPosition(input.getCaretPosition() + 1);
                break;

            default:
                break;
        }

    }

I have omitted the remainder of the class as I don't think it is necessary. I am intending to move away from the KeyEventListener and using KeyBindings instead, and I expect that this will solve the problem. However I still would like to know what might cause this.

EDIT: There was a mistake in the code. It works now.

diestl
  • 2,020
  • 4
  • 23
  • 37
  • 1
    *" This is primarily to circumvent the fact that `System.console()` returns `null` from within an IDE like eclipse."* So this entire hack comes down to trying to fix something that should be fixed in the IDE (or the IDE settings or in the launch method)? Can't say I'm keen to help with that. – Andrew Thompson Jun 26 '13 at 10:51
  • Grr `KeyListener`.. Have a read on [How to Use Key Bindings](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html) maybe a bit more coding depending on the amount of keys but it saves time when focus problems arise from using the `KeyListener` *Key listeners have their place as a low-level interface to keyboard input, but for responding to individual keys key bindings are more appropriate and tend to result in more easily maintained code* – David Kroukamp Jun 26 '13 at 10:55
  • @Andrew Yes it should be fixed in the IDE but I don't know how. Also I wanted to try to write a very simple Swing application so no harm done :) – diestl Jun 26 '13 at 10:56
  • 1
    *"I wanted to try to write a very simple Swing application"* Your mistake there is presuming it is *simple* to implement a console. Put this project on hold until you get more experience, particularly with the IDE. By then you'll probably have figured how to run it in Eclipse without having to 'roll your own' console. – Andrew Thompson Jun 26 '13 at 10:59
  • 1
    @David The reason for using a KeyListener in this instance was that I needed a standard response for approx 50 characters. I will however change the few special keys to key bindings. Thanks. – diestl Jun 26 '13 at 11:00
  • @Andrew I found that while writing a Console application was certainly not easy, it was mainly the logic behind the UI that proved challenging, not UI itself. I guess I was somewhat ambiguous. – diestl Jun 26 '13 at 12:11
  • 1
    This question appears to be off-topic because it is too localized. – casperOne Jun 26 '13 at 12:21

1 Answers1

1

You skipped the break before line case KeyEvent.VK_UP:

SeniorJD
  • 6,946
  • 4
  • 36
  • 53