首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Swing 重導向 System.out 輸出至 JTextArea 完整實作:自訂 PrintStream 與執行緒安全

     編輯:程式設計綜合問答

在 Swing 應用中將控制台輸出(System.out.println()、e.printStackTrace())重導向至 JTextArea 顯示,需自訂 PrintStream 覆寫 write() 方法,並確保 UI 更新在事件調度執行緒 (EDT) 執行。

核心實作類別

public class ConsoleRedirectOutputStream extends OutputStream {
    private final JTextArea textArea;
    private final StringBuilder buffer = new StringBuilder();
    
    public ConsoleRedirectOutputStream(JTextArea textArea) {
        this.textArea = textArea;
    }
    
    @Override
    public void write(int b) throws IOException {
        char c = (char) b;
        if (c == '\n' || c == '\r') {
            flushBuffer();
        } else {
            buffer.append(c);
        }
    }
    
    private void flushBuffer() {
        final String text = buffer.toString();
        buffer.setLength(0);
        // 必須在 EDT 更新 UI
        SwingUtilities.invokeLater(() -> {
            textArea.append(text + "\n");
            textArea.setCaretPosition(textArea.getDocument().getLength()); // 自動捲動到底
        });
    }
    
    @Override
    public void flush() throws IOException { flushBuffer(); }
    @Override
    public void close() throws IOException { flushBuffer(); }
}

// 使用方式
JTextArea consoleArea = new JTextArea();
consoleArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(consoleArea);

PrintStream consoleStream = new PrintStream(new ConsoleRedirectOutputStream(consoleArea), true);
System.setOut(consoleStream);
System.setErr(consoleStream); // 也導向錯誤輸出

完整視窗範例

public class ConsoleWindow extends JFrame {
    public ConsoleWindow() {
        setTitle("應用程式控制台");
        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        setSize(600, 400);
        setLocationRelativeTo(null);
        
        JTextArea textArea = new JTextArea();
        textArea.setEditable(false);
        textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
        add(new JScrollPane(textArea), BorderLayout.CENTER);
        
        // 重導向
        PrintStream ps = new PrintStream(new ConsoleRedirectOutputStream(textArea), true);
        System.setOut(ps);
        System.setErr(ps);
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new ConsoleWindow().setVisible(true));
        // 測試輸出
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("背景執行緒輸出: " + i);
                try { Thread.sleep(500); } catch (InterruptedException ignored) {}
            }
        }).start();
    }
}

關鍵注意事項

  • 執行緒安全:所有 textArea.append() 必須包裹在 SwingUtilities.invokeLater() 中。
  • 緩衝處理:write(int) 逐字元呼叫,需自行緩衝至換行再刷新,避免大量 invokeLater 導致效能問題。
  • 記憶體洩漏:長時間運行應限制 JTextArea 最大行數,定期移除舊內容(textArea.replaceRange("", 0, endIndex))。
  • 還原:應用結束前可 System.setOut(originalOut) 還原標準輸出。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved