2013-02-05 24 views
3

编辑:我已编辑帖子来澄清我的问题,现在我自己,有更多的理解。System.out.println到JTextArea

正如标题所示,我在执行应用程序的任务时尝试在我的GUI中输出控制台到我的JTextArea

这是我目前在做什么:

public class TextAreaOutputStream extends OutputStream 
{ 

    private final JTextArea textArea; 

    private final StringBuilder sb = new StringBuilder(); 

    public TextAreaOutputStream(final JTextArea textArea) 
    { 
     this.textArea = textArea; 
    } 

    @Override 
    public void flush() 
    { 
    } 

    @Override 
    public void close() 
    { 
    } 

    @Override 
    public void write(int b) throws IOException 
    { 

     if (b == '\r') 
      return; 

     if (b == '\n') 
     { 
      final String text = sb.toString() + "\n"; 
      SwingUtilities.invokeLater(new Runnable() 
      { 
       public void run() 
       { 
        textArea.append(text); 
       } 
      }); 
      sb.setLength(0); 
     } 
     sb.append((char) b); 
    } 
} 

以上将成功地重新直接System.out我上面的输出流,因此寄发一个事件到EventQueue来更新我的GUI(JTextArea)。

这里是问题:

目前使用invokeLater()意志,因为它说的文档:

Causes runnable to have its run method called in the dispatch thread of the EventQueue. This will happen after all pending events are processed.

所以我真正想要做的是履行我更新的图形用户界面(通话run() )在处理EventQueue中的所有其他事物之前。

是否有可能将一个事件基本注入到我的EventQueue中?或者有人可以指点我在这方面的一个体面的教程?

感谢,

+0

_“上面在这个意义上的作品,我得到系统输出到我的JTextArea,但是当我试图做到这一点在的actionPerformed(),我没有得到任何输出解决方案” _和你确定你通过了所有这些如果是?没有很好的理由为什么一个'System.out'调用可以工作,另一个失败 – Robin

回答

9

下面的示例文本区创建框架和重定向的System.out它:

import java.awt.BorderLayout; 
import java.awt.Container; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.io.PrintStream; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingUtilities; 

public class JTextAreaOutputStream extends OutputStream 
{ 
    private final JTextArea destination; 

    public JTextAreaOutputStream (JTextArea destination) 
    { 
     if (destination == null) 
      throw new IllegalArgumentException ("Destination is null"); 

     this.destination = destination; 
    } 

    @Override 
    public void write(byte[] buffer, int offset, int length) throws IOException 
    { 
     final String text = new String (buffer, offset, length); 
     SwingUtilities.invokeLater(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        destination.append (text); 
       } 
      }); 
    } 

    @Override 
    public void write(int b) throws IOException 
    { 
     write (new byte [] {(byte)b}, 0, 1); 
    } 

    public static void main (String[] args) throws Exception 
    { 
     JTextArea textArea = new JTextArea (25, 80); 

     textArea.setEditable (false); 

     JFrame frame = new JFrame ("stdout"); 
     frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     Container contentPane = frame.getContentPane(); 
     contentPane.setLayout (new BorderLayout()); 
     contentPane.add (
      new JScrollPane (
       textArea, 
       JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
       JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), 
      BorderLayout.CENTER); 
     frame.pack(); 
     frame.setVisible (true); 

     JTextAreaOutputStream out = new JTextAreaOutputStream (textArea); 
     System.setOut (new PrintStream (out)); 

     while (true) 
     { 
      System.out.println ("Current time: " + System.currentTimeMillis()); 
      Thread.sleep (1000L); 
     } 
    } 
} 
+0

嗯我的方法有什么问题?我在这里可以看到的只是您重新创建了我的解决方案?你能指出它解决我的问题的地方吗? – buymypies

+1

睡在[*初始线程*](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html)上没有任何问题,但应该在EDT上构建GUI组件。 – trashgod

+0

你的方法有几个小问题,即你输出每个''n''两次,但没有任何可能导致你描述的问题。你确定'!“”。equals(targetFile.getText())'和'checkBox.isSelected()'都是真的吗? –

4

你的错误必须位于其他地方,你还没有告诉我们呢。这里是一个非常简单的演示按预期几乎相同的代码,你(我只固定的小问题)的工作原理:

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.io.PrintStream; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

public class TextAreaOutputStream extends OutputStream { 

    private final JTextArea textArea; 

    private final StringBuilder sb = new StringBuilder(); 

    public TextAreaOutputStream(final JTextArea textArea) { 
     this.textArea = textArea; 
    } 

    @Override 
    public void flush() { 
    } 

    @Override 
    public void close() { 
    } 

    @Override 
    public void write(int b) throws IOException { 

     if (b == '\r') { 
      return; 
     } 

     if (b == '\n') { 
      final String text = sb.toString() + "\n"; 

      textArea.append(text); 
      sb.setLength(0); 
     } else { 
      sb.append((char) b); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame frame = new JFrame(TextAreaOutputStream.class.getSimpleName()); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       JTextArea ta = new JTextArea(24, 80); 
       System.setOut(new PrintStream(new TextAreaOutputStream(ta))); 
       frame.add(new JScrollPane(ta)); 
       frame.pack(); 
       frame.setVisible(true); 
       System.out.println("Textarea console initiated"); 
       Timer t = new Timer(1000, new ActionListener() { 

        int count = 1; 

        @Override 
        public void actionPerformed(ActionEvent e) { 
         System.out.println("Outputting line " + count++ + " to the console. Working properly, no?"); 
        } 
       }); 
       t.start(); 
      } 
     }); 
    } 
} 
+0

这个问题是我自己对'invokeLater()'的愚蠢和误解。我的解决方案正在工作,但并非如我所愿,即我的GUI已更新,但直到处理完EventQueue中的所有其他内容之后 - 即上面代码段中的'...'。这不是我想要的。 – buymypies

+0

@ buymypies Btw,'JTextArea.append'是线程安全的,所以不需要将它包装在'invokeLater()'中。 –

+0

请参阅我的编辑我的问题,希望我已经更清楚了我正在尝试做什么。 – buymypies

0

如果你想看到在文本区域滚动效果,然后,而不是附加的输出,你可以把新的文字放在开头。 例子:

HttpURLConnection con = (HttpURLConnection) (new URL(url[0]).openConnection()); 
con.setInstanceFollowRedirects(false); 
con.connect(); 
int responseCode = con.getResponseCode(); 
String location = con.getHeaderField("Location"); 
textArea.setText(url[0] +"," +responseCode+"," +location+"\n"+textArea.getText()); //new text is prefixed to the existing text 
textArea.update(textArea.getGraphics());