2012-02-11 7 views
1

Эй, ребята, я делаю приложение терминала с помощью Swing и Apache Commons. Я смог перенаправить System.out и System.err на JTextArea легко, но как это сделать для System.in? Нужно ли переопределить методы Inputstream? Нужно ли преобразовать String из JTextArea в массив байтов, а затем передать его InputStream? Примеры кода были бы хороши.Переадресовать System.in на компонент качания

ответ

4

Недавно я попробовал то же самое, вот мой код:

class TexfFieldStreamer extends InputStream implements ActionListener { 

    private JTextField tf; 
    private String str = null; 
    private int pos = 0; 

    public TexfFieldStreamer(JTextField jtf) { 
     tf = jtf; 
    } 

    //gets triggered everytime that "Enter" is pressed on the textfield 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     str = tf.getText() + "\n"; 
     pos = 0; 
     tf.setText(""); 
     synchronized (this) { 
      //maybe this should only notify() as multiple threads may 
      //be waiting for input and they would now race for input 
      this.notifyAll(); 
     } 
    } 

    @Override 
    public int read() { 
     //test if the available input has reached its end 
     //and the EOS should be returned 
     if(str != null && pos == str.length()){ 
      str =null; 
      //this is supposed to return -1 on "end of stream" 
      //but I'm having a hard time locating the constant 
      return java.io.StreamTokenizer.TT_EOF; 
     } 
     //no input available, block until more is available because that's 
     //the behavior specified in the Javadocs 
     while (str == null || pos >= str.length()) { 
      try { 
       //according to the docs read() should block until new input is available 
       synchronized (this) { 
        this.wait(); 
       } 
      } catch (InterruptedException ex) { 
       ex.printStackTrace(); 
      } 
     } 
     //read an additional character, return it and increment the index 
     return str.charAt(pos++); 
    } 
} 

и использовать его как это:

JTextField tf = new JTextField(); 
    TextFieldStreamer ts = new TextFieldStreamer(tf); 
    //maybe this next line should be done in the TextFieldStreamer ctor 
    //but that would cause a "leak a this from the ctor" warning 
    tf.addActionListener(ts); 

    System.setIn(ts); 

было некоторое время, так как я закодированы Java, так что я не может быть вверх с современными моделями. Вероятно, вы также должны перегрузить int available(), но мой пример состоит только из минимального минимума, чтобы заставить его работать с функцией BufferedReader s readLine().

Edit: Для этого, чтобы работать на JTextField вы должны использовать implements KeyListener вместо implements ActionListener, а затем использовать addKeyListener(...) на вашем TextArea. Функция, что вам нужно вместо actionPerformed(...) это public void keyPressed(KeyEvent e), а затем вы должны проверить if (e.getKeyCode() == e.VK_ENTER) и вместо того, чтобы использовать весь текст, который вы просто использовать подстроку из последней строки перед курсором с

//ignores the special case of an empty line 
//so a test for \n before the Caret or the Caret still being at 0 is necessary 
int endpos = tf.getCaret().getMark(); 
int startpos = tf.getText().substring(0, endpos-1).lastIndexOf('\n')+1; 

для входной строки. Потому что иначе вы читали бы весь TextArea каждый раз, когда вы нажимаете enter.

+0

Cool Ill просто нужно изменить его, чтобы он занимал последнюю строку JTextArea. Большое спасибо – Giannis

+0

@ latusaki, не совсем вам придется немного модифицировать его, так как 'JTextArea' не генерирует' ActionEvent 'afaik. Вы можете либо сделать несвязанную кнопку, либо добавить к ней прослушиватель действий или переопределить 'JTextArea', и поймать ключевые события, чтобы искать« Ctrl-Enter »или что-то подобное, а затем запускать« ActionEvent »самостоятельно. – PeterT

+0

Метод чтения не вызван по какой-либо причине во время тестирования с текстовым полем. – Giannis

1

Вам необходимо создать собственную реализацию InputStream, которая берет свой вход от любого компонента Swing, который вы хотите ... в основном есть буфер, который вы копируете текст с вашего компонента Swing, и который служит источником для InputStream (который из курс должен блокироваться, если вход не доступен).

Смежные вопросы