Reading from keyboard without pressing "enter" using JCurses

4.5k views Asked by At

I am writing an application that requires me to read a key from console without having to wait for the user to hit enter. I have read that JCurses library could help.

I tried using Toolkit.readCharacter() like this:

InputChar c = Toolkit.readCharacter();
system.out.println(c.getCharacter());

But the problem was that the readCharacter() method does not end execution no matter how many characters you input. Even if you press enter, it still seems that it is waiting for you to enter a character.

I really appreciate any help using JCurses, or any other way would do.

2

There are 2 answers

2
x4nd3r On

Java Curses has a couple of specific keystroke recognition methods, but tying yourself down to an external library for a single function may not be the best solution.

What you are after could be achieved by creating a terminal-style Swing application, and using a KeyListener to detect keystroke events. However, MadProgrammer notes in How to make esc stop a method that such a solution may have "focus issues".

So if you want to trace specific keystrokes, or want to affect program behaviour based on different user inputs, I would recommend using key bindings which are implemented as part of Swing.

e.g.

component.getInputMap(WHEN_IN_FOCUSED_WINDOW).put
    (KeyStroke.getKeyStroke("F1"),"actionName");
component.getActionMap().put("actionName", yourAction);

Where component is any JComponent object (assumably a terminal display), and yourAction is any Swing action. Using the paramaterised form of getInputMap() as shown here is preferable for a "console" application, as the user will necessarily making keystrokes within the top level window, and therefore component focus is irrelevant.

0
codeDr On

This program worked for me.
You need to call Toolkit.init() to put the terminal into cbreak() mode. And remember to call Toolkit.shutdown() before exiting.

A couple of drawbacks.

  • jcurses automatically puts the tty into cbreak mode, and jcurses does not provide a method for manipulating the curses library directly.
  • once you are in jcurses, the output is in cbreak mode and direct strings from java have newlines, but no carriage returns.
  • the developers of jcurses only implemented the curses part of owning the whole screen. jcurses seems overkill if all you want is cbreak mode.

The program.

import jcurses.system.CharColor;
import jcurses.system.InputChar;
import jcurses.system.Toolkit;

public class itest 
{

    public static void main(String[] args) 
    {
        int y = 0;
        CharColor color = new CharColor(CharColor.BLACK, CharColor.WHITE);
        Toolkit.init();
        while (true) {
            InputChar c = Toolkit.readCharacter();
            if ('q' == c.getCharacter())
                break;
            Toolkit.printString(String.format("c : %c", c.getCharacter()), 0, y++, color);
        }
        Toolkit.shutdown();
    }
}