简体   繁体   English

Java控制台输出重叠Scanner

[英]Java Console output overlapping Scanner

I'm trying to create a console input system which at the same time is able to print output: 我正在尝试创建一个控制台输入系统,同时能够打印输出:

new Thread(() ->{ //asynchronous output test every 2 sec
        while(true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("test");
        }
    }).start();

This is how i get the user input: 这是我获得用户输入的方式:

String line = scanner.nextLine();

However when I'm typing and there's an output at the same time, this is the result: 但是,当我打字并且同时有输出时,结果如下:

Test
Test
TestI'm try
Testing to type

Is there a way to display the input line always at the bottom of the console? 有没有办法在控制台底部始终显示输入线?

The solution would be to get the user's input every time he types and store what is actually written in a variable. 解决方案是在每次键入和存储实际写入变量的内容时获取用户的输入。 Then, before writing "Test", clear the amount of characters your user's input is made of by printing \\b several times in the console. 然后,在编写“测试”之前,通过在控制台中多次打印\\b清除用户输入的字符数量。 After that you can print the user's input again to make it feel like "Test" was just printed above. 之后,您可以再次打印用户的输入,使其感觉上面刚刚打印出“测试”。

The tricky part is to get the user's input just as he types. 棘手的部分是在输入时获取用户的输入。 I used the JLine lib in order to achieve that. 我使用JLine lib来实现这一目标。 Also I made sure that the "test" printing thread was getting the inputLine in a synchronized way for thread safety. 此外,我确保“测试”打印线程以同步方式获取inputLine以确保线程安全。

private static String inputLine = "";

synchronized static String getInputLine() {
    return inputLine;
}

synchronized static void setInputLine(String line) {
    inputLine = line;
}

public static void main(String[] args) {

    char c;
    char allowed[] = {'a','b','c','d','e','f','g','h','i','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\n','\r','\b'};

    ConsoleReader reader;
    PrintWriter out = new PrintWriter(System.out);

    new Thread(() ->{ //Asynchronous output test every 2 sec
        while(true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            String erase = ""; //Prepare a string as long as the input made \b characters
            for(int i = 0 ; i < getInputLine().length() ; i++)
                erase += '\b';

            String whitespace = ""; //Prepare a string of whitespaces to override the characters after "test" (thus -4)  
            for(int i = 0 ; i < getInputLine().length() - 4 ; i++)
                whitespace += ' ';

            out.print(erase); //Erase the input line                
            out.println("test" + whitespace);
            out.print(getInputLine());
            out.flush();
        }
    }).start();

    try {
        reader = new ConsoleReader();
        reader.setBellEnabled(false);

        while(true){
            c = (char) reader.readCharacter(allowed);

            if(c == '\r' || c == '\n') {

                //Do something with the input

                setInputLine("");
                out.println();
            } else if(c == '\b') { //Backspace
                String line = getInputLine();
                setInputLine(line.substring(0, line.length()-1));
                out.print(c);
                out.print(" "); //Print whitespace to erase trailing char
                out.print(c); //Backspace again to send the carret back to the last char
            } else {
                setInputLine(getInputLine() + c);
                out.print(c);
            }

            out.flush();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

This program works for me but only outside of my IDE. 这个程序适合我,但只能在我的IDE之外。 Note that the program is stuck in an infinite loop so if you want to shut it down, you have to handle it from the code with a "quit" command for example. 请注意,程序停留在无限循环中,因此如果要关闭它,则必须使用“quit”命令从代码中处理它。

Edit: also set the inputLine in a synchronized way. 编辑:还以同步方式设置inputLine。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM