Эмуляция пользовательского ввода для java.util.Scanner - PullRequest
1 голос
/ 04 октября 2008

Я пишу игру на Java и хочу, чтобы пользователь мог вводить данные как из командной строки, так и из моего графического интерфейса. В настоящее время я использую этот метод для получения ввода:

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

Я хочу продолжать использовать это, но позвольте событию mousePressed эмулировать пользователя, который также вводит свои данные. Это не очень эффективное решение, но оно имеет смысл в моем приложении. Итак, вопрос: как мне смоделировать ввод пользователя в System.in со стороны кода?

Ответы [ 4 ]

1 голос
/ 05 октября 2008

Это возможно - самая простая замена для System.in будет PipedInputStream . Это должно быть подключено к PipedOutputStream , который пишет из другого потока (в данном случае, потока Swing).

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);
    }

}

Однако, возможно, было бы лучше переосмыслить игровую логику, чтобы вообще отключить потоки в режиме GUI.

0 голосов
/ 04 октября 2008

Если честно, после перечитывания вашего вопроса я не совсем уверен, что вы хотите.

В любом случае, возможно, вам нужно проверить метод java.lang.System.setIn (InputStream in). Это позволит вам изменить читатель, который используется для чтения ввода с терминала (т.е. изменить его с фактического терминала на тот, который вам нравится)

0 голосов
/ 04 октября 2008

Предполагая, что у вас много операций, подобных приведенному примеру, вы можете рассмотреть интерфейсный подход, описанный Richie_W, но создать одну подпрограмму для каждой операции, а не общие методы "in / out".

Например:

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

Ваша реализация командной строки понятна; теперь ваша реализация GUI может использовать соответствующий диалог для каждой логической операции, а не просто текстовую область, которая на самом деле является версией командной строки.

Кроме того, проще писать модульные тесты, потому что в своих тестах вы можете заглушить эти процедуры любым способом.

0 голосов
/ 04 октября 2008

Я однажды сделал приложение, которое можно запустить через командную строку или с помощью графического интерфейса.
То, как я это сделал, было определить интерфейс (названный IODevice), который определил следующие методы:

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


У меня было два класса, которые реализовали этот интерфейс - один использовал терминал главного компьютера (как вы делаете сейчас), а другой использовал JTextArea (выход) / JOptionPane (вход).

Возможно, вы могли бы сделать нечто подобное - чтобы изменить используемое устройство ввода, просто измените экземпляр IODevice.


Надеюсь, это пригодится.

...