2

I would like to ask to the user if he could press a key before continuing. Then my program will wait for that during 10 seconds. If nothing is done, then, I would like to be able to exit the program.

My problem is that the function scanner block my program (until the user have pressed a key) and doesn't allow the program to execute the end.

Do you have any idea of what I could do/use instead of scanner? I am just a beginner in java so please, be indulgent with me.

import java.util.Scanner;

public class Test{
    public Test(){
        Scanner scan = new Scanner(System.in);
         boolean first = true;
         System.out.println("Press any key to start.\n"); 
        for(int fr = 0; fr <11; fr++){
            System.out.println(fr);
                try{
                    Thread.sleep(1000);

                } catch (Exception e) {
                    System.err.println("error -> "+e.getMessage()); // in case of exception, error message
                }
        if(fr == 10){
            Default def = new Default();
        }else if(scan.hasNext() == true){
            //System.out.println("Hello");
            User user = new User(); // or exit, it doesn't matter
        }
        }
    }
}
Beginner
  • 161
  • 4
  • 12
  • 1
    If the android tag is not a mistake, you need to re-design your program to display on the android ui, and to be a collection of brief-in-time methods called from android's event-driven ui. Start over with some basic android examples and work from there back towards your goal. – Chris Stratton Jul 28 '14 at 13:13
  • 1
    I think you added the Android tag by mistake, because the code doesn't even relate to android. – RvdK Jul 28 '14 at 15:21
  • There is answer in the following question which you may be able to adapt to your needs: http://stackoverflow.com/questions/7872846/how-to-read-from-standard-input-non-blocking – Andreas Jul 28 '14 at 20:41

2 Answers2

0

Use a KeyListener.

First make a Component, give it the focus, and add a KeyListener.

Example code:

Component comp = new Componenet();
comp.addKeyListener(new KeyListener() {
    public void keyTyped(KeyEvent e) {
        System.out.print("Hello");
    }

    public void keyPressed(KeyEvent e) {}
    public void keyReleased(KeyEvent e) {}
});

try {
    Thread.sleep(1000);
} catch (Exception e) {
}
System.exit(0);
Ypnypn
  • 933
  • 1
  • 8
  • 21
  • Thank you for your reply. I am looking for ways to create a component. I think your code is not very close of what I want... Is it possible to juste replace "scan.hasNext()" by the keyListener ? I am a little bit lost, sorry. – Beginner Jul 29 '14 at 09:38
  • @Beginner To create a component, simply put `Component comp = new Component()` (the top line here). Then, when a key is pressed, it triggers the event keyTyped(), which does whatever you want (in this case print "Hello"). This can be instead of the `scan.hasNext()`. – Ypnypn Jul 29 '14 at 16:12
0

A possible solution is using a different thread to read user input from the scanner. Here is an example code:

Scanner scanner = new Scanner(System.in);
ExecutorService scannerExecutor = Executors.newSingleThreadExecutor();
Future<String> nextLineFuture = scannerExecutor.submit(scanner::nextLine);
/* For Java < 8:
Future<String> nextLineFuture = scannerExecutor.submit(new Callable<String>() {
    @Override
    public String call() throws Exception {
        return scanner.nextLine();
    }
});
 */

String input;
try {
    input = nextLineFuture.get(5, TimeUnit.SECONDS);
}
catch (TimeoutException e) {
    input = "Nothing was entered";
}
catch (InterruptedException | ExecutionException e) {
    // Handle the exception
    return;
}

System.out.println(input);

However, you need to keep in mind some of the issues with this:

  • Even when nextLineFuture.get(...) throws TimeoutException, the nextLine call will still be running. If you later run scannerExecutor.submit(scanner::nextLine) again, the input will first be consumed by the previous call, so you should make sure to have a reference to the last Future created whose result hasn't been used yet.

  • Because of the issue above, this approach will not work if you need to use different scanner methods such as nextBoolean, nextInt, etc. You can, however, always use nextLine on the primary scanner and then parse the line manually (for example, by using yet another scanner)

izstas
  • 5,004
  • 3
  • 42
  • 56
  • I will try your method, but I don't understand the third line. Can you explain it to me a little bit more ? – Beginner Jul 28 '14 at 22:13
  • What exactly does confuse you? It uses [method references](http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html) (Java 8+), I added alternative code to my answer. – izstas Jul 29 '14 at 06:43
  • I am working on eclipse, and it doesn't know the third line, send me back an error message. – Beginner Jul 29 '14 at 10:38
  • Try to comment out the third line, and instead uncomment the block I added in the last edit. – izstas Jul 29 '14 at 11:01