Emulating user input for java.util.Scanner

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-11 08:06:02

问题


I'm writing a game in Java, and I want the user to be able to provide input from both the command line and my GUI. Currently, I use this method to get input:

    static String getInput(){
        System.out.println("Your move:");
        Scanner sc = new Scanner(System.in);
        return sc.nextLine();
    }

I want to keep using this, but let a mousePressed event emulate the user actually typing in their input as well. It's not that efficient of a solution, but it makes sense in my application. So the question is: how do I simulate a user typing to System.in from the code side?


回答1:


This is possible - the easiest substitution for System.in would be a PipedInputStream. This must be hooked up to a PipedOutputStream that writes from another thread (in this case, the Swing thread).

public class GameInput {

    private Scanner scanner;

    /**CLI constructor*/
    public GameInput() {
        scanner = new Scanner(System.in);
    }

    /**GUI constructor*/
    public GameInput(PipedOutputStream out) throws IOException {
        InputStream in = new PipedInputStream(out);
        scanner = new Scanner(in);
    }

    public String getInput() {
        return scanner.nextLine();
    }

    public static void main(String[] args) throws IOException {
        GameInput gameInput;

        PipedOutputStream output = new PipedOutputStream();
        final PrintWriter writer = new PrintWriter(output);
        gameInput = new GameInput(output);

        final JTextField textField = new JTextField(30);
        final JButton button = new JButton("OK");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String data = textField.getText();
                writer.println(data);
                writer.flush();
            }
        });

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(textField);
        frame.getContentPane().add(button);
        frame.pack();
        frame.setVisible(true);

        String data = gameInput.getInput();
        System.out.println("Input=" + data);
        System.exit(0);
    }

}

However, it might be better to rethink your game logic to cut out the streams altogether in GUI mode.




回答2:


To be honest, after re-reading your question I'm not exactly sure what you want.

Anyway, perhaps you need to check out the method java.lang.System.setIn(InputStream in). This will allow you to change what reader is used to read input from the terminal (i.e. changing it from the actual terminal to what ever you like)




回答3:


Assuming you have many operations like the given example, you might consider the interface approach described by Richie_W but make one routine per operation rather than generic "in/out" methods.

For example:

public interface IGameInteraction
{
    public String askForMove( String prompt );
    public boolean askAreYouSure( String prompt );
}

Your command-line implementation is clear; now your GUI implementation could use an appropriate dialog for each logical operation rather than just be a text area that's really just the command-line version.

Furthermore this is easier to write unit tests against because in your tests you can stub out these routines in any manner.




回答4:


I made an application once that could run via the command line or using a GUI.
The way I did this was to define an Interface (named IODevice) which defined the following methods:

  • public String getInput();
  • public void showOutput(String output);

  • I then had two classes which implemented this interface - One used the host computer's terminal (as you are doing now) and one used a JTextArea (output) / JOptionPane (input).

    Perhaps you could do something similar - To change the input device used, simply change the instance of the IODevice.


    Hope this is of some use.



    来源:https://stackoverflow.com/questions/170854/emulating-user-input-for-java-util-scanner

    易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
    该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!