2012-02-11 27 views
1

嘿,我正在使用Swing和Apache Commons製作終端應用程序。我能夠很容易地將System.outSystem.err重定向到JTextArea,但我該怎麼做System.in?我需要覆蓋Inputstream方法嗎?我是否需要將StringJTextArea轉換爲字節數組,然後將它傳遞給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(),但我的示例僅包含最低限度使其與BufferedReaderreadLine()函數配合使用。

編輯:對於這一個JTextField必須使用implements KeyListener而不是implements ActionListener,然後在你的文本區使用addKeyListener(...)工作。你需要的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; 

的輸入字符串。因爲否則,每次按Enter時都會讀取整個TextArea。

+0

Cool Ill只需更改它,以便它佔用JTextArea的最後一行。非常感謝 – Giannis 2012-02-11 21:51:04

+0

@latusaki,因爲'JTextArea'不會生成'ActionEvent'afaik,所以不需要修改它。你可以創建一個不相關的按鈕並添加動作偵聽器,或者重寫'JTextArea'並捕獲鍵盤事件以查找'Ctrl-Enter'或類似的東西,然後自己觸發'ActionEvent'。 – PeterT 2012-02-11 21:58:40

+0

在使用文本字段進行測試時,讀取方法不會因某種原因而被調用。 – Giannis 2012-02-11 22:36:21

1

您需要創建自己的實現的InputStream這需要從任何你想要的Swing組件的輸入...基本上有您複製文本從您的Swing組件的緩衝區,並且充當用於InputStream源(其中如果沒有輸入可用,則需要阻止課程)。