Настройка System.in для чтения из JTextField
Я ищу направление о том, как заменить System.in
с InputStream
который читает прямо из JTextField
,
До сих пор мой подход был в значительной степени методом проб и ошибок. У меня сейчас есть;
JTextField input = new JTextField();
System.setIn(new InputStream() {
int ptr = 0;
@Override
public int read() throws IOException {
int c;
try {
c = input.getText().charAt(ptr);
}
catch (IndexOutOfBoundsException ioob) {
return 0;
}
ptr++;
return c;
}
});
Это дает NoSuchElementException
как в попытках чтения, когда ввод пуст, и я предполагаю, что никогда не может найти разделитель.
Какой подход мне не хватает?
2 ответа
Ну, это метод, который я использовал, чтобы заставить его работать правильно. Если кто-то может улучшить этот ответ, не стесняйтесь.
final LinkedBlockingQueue<Character> sb = new LinkedBlockingQueue<Character>();
final JTextField t = new JTextField();
t.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
sb.offer(e.getKeyChar());
}
...
});
System.setIn(new BufferedInputStream(new InputStream() {
@Override
public int read() throws IOException {
int c = -1;
try {
c = sb.take();
} catch(InterruptedException ie) {
}
return c;
}
}));
Вы смотрите на полпути, но:
Из Javadocs
Этот метод блокируется до тех пор, пока не будут доступны входные данные, не будет обнаружен конец потока или сгенерировано исключение.
http://docs.oracle.com/javase/1.4.2/docs/api/java/io/InputStream.html
Таким образом, ваш метод должен просто ждать нажатия клавиши. Либо путем обработки NoSuchElementException, либо KeyListener, который проверяет, сколько (новых?) Символов доступно.
Семантика этого InputStream отличается от консольной, поэтому вам нужно принять некоторые конструктивные решения о том, как обрабатывать изменения, а не только нажатия клавиш.