2013-02-05 56 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());