Java,console輸出實時的轉向GUI textbox

1 簡單入門例子

  入門例子是從參考文獻2與3中粘過來的內容。
  在Swing中,若是須要重定向System.err和System.out到一個JTextPane或一個JTextArea,你僅須要覆寫OutputStream類的write()方法,以追加文本到文本組件。下面給一個關於JTextArea的例子。html

private JTextArea textArea = new JTextArea(4, 25);

// 本質上至關於多線程的更新JTextArea內容
private void updateTextArea(final String text) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      textArea.append(text);
    }
  });
}
 
private void redirectSystemStreams() {
  OutputStream out = new OutputStream() {
    @Override
    public void write(int b) throws IOException {
      updateTextArea(String.valueOf((char) b));
    }
 
    @Override
    public void write(byte[] b, int off, int len) throws IOException {
      updateTextArea(new String(b, off, len));
    }
 
    @Override
    public void write(byte[] b) throws IOException {
      write(b, 0, b.length);
    }
  };
 
  System.setOut(new PrintStream(out, true));
  System.setErr(new PrintStream(out, true));
}

@Test
public void run() {
     // 使用,調用redirectSystemStreams()便可。    
     redirectSystemStreams();

     // 下面這句話會轉向textArea中輸出
     System.out.println("hello, world");
}

2 實時輸出問題

  redirectSystemStreams方法,本質上是多線程的更新JTextArea內容。在處理Swing上的點擊事件時,事件處理返回以前,其餘事件是不能觸發的,界面相似於卡住的情況。
  所以,在Swing點擊事件結束後,更新JTextArea內容的線程才能運行,這樣的效果是內容輸出是非實時的。
  怎樣解決這個問題呢?在事件處理函數裏面,重開一個線程,在這個新開的線程裏面,執行比較耗時的計算與相應的打印內容。這樣的話,事件處理函數所在的線程會快速的線束,其它更新Swing的JTextArea內容的線程才能被執行。
  下面以僞代碼的形式,給出一個例子,說明事件處理函數的寫法。java

public class InstallBtnListener implements ActionListener {

    // 日誌頁面類,該類有一個JTextArea屬性,是打印內容目標輸出位置;
    private LogFrame logFrame = new LogFrame();
        
    public InstallBtnListener() {
        super();        
        
        // 使輸出轉向JTextArea;
        // 這裏我封閉了個類,重點是,將JTextArea傳過去,且調用redirectSystemStreams方法
        new RedirectingPrint(logFrame.getTextArea()).redirectSystemStreams();
    }

    @Override
    public void actionPerformed(ActionEvent e) {            

        // 在事件處理函數裏面,重開一個線程,在這個新開的線程裏面,執行比較耗時的計算與相應的打印內容
        new Thread(new Runnable() {
            @Override
            public void run() {                                
                // 比較耗時的計算與相應的打印內容代碼寫在這裏                                
            }
        }).start();
        
    }
}

// JButton點擊事件 
jbutton.addActionListener(new InstallBtnListener());

3 總結

  以上,就解決了輸出實時性的問題。
  下面有一段話,從參考文獻1中粘過來的,用它來總結下這個問題。多線程

通常說來,耗時的操做不該該在事件處理方法中執行,由於事件處理返回以前,其餘事件是不能觸發的,界面相似於卡住的情況,因此在獨立的線程上執行比較耗時的操做可能更好,這會當即更新用戶界面和釋放事件派發線程去派發其餘的事件。

4 參考文獻

[1] https://blog.csdn.net/yiziwei... (java基礎學習總結——java.awt.EventQueue.invokeLater幹什麼用的)
[2] https://billwaa.wordpress.com... ([Java] GUI Console Output)
[3] http://unserializableone.blog... (Redirecting System.out and System.err to JTextPane or JTextArea)
[4] https://stackoverrun.com/cn/q... (如何在eclipse中打印到textArea而不是控制檯?)
[5] https://stackoverflow.com/que...app

相關文章
相關標籤/搜索