将System.in重定向到swing组件

时间:2012-02-11 21:11:50

标签: java swing terminal

嘿伙计们我正在使用Swing和Apache Commons制作终端应用程序。我能够轻松地将System.outSystem.err重定向到JTextArea,但我如何为System.in执行此操作?我是否需要覆盖Inputstream方法?我是否需要将StringJTextArea转换为字节数组,然后将其传递给InputStream?代码示例很不错。

2 个答案:

答案 0 :(得分: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 readLine()函数一起使用。

修改:要使其适用于JTextField,您必须使用implements KeyListener代替implements ActionListener,然后在TextArea上使用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。

答案 1 :(得分:1)

你需要创建自己的InputStream实现,从你想要的任何Swing组件中获取它的输入...基本上有一个缓冲区,你可以从Swing组件复制文本,并作为{的源{1}}(如果没有可用的输入,当然需要阻止)。