Come impostare il stream di output su TextArea

Sto provando a creare un pannello della GUI per un programma e mi piacerebbe tutto, che normalmente stamperebbe sul mio prompt dei comandi, per stampare su un object TextArea. Ho il pannello GUI formattato per la maggior parte, ma non riesco a stampare il testo su TextArea, ecco il mio file:

package guipanel; import javax.swing.*; import java.awt.*; import java.io.*; /** * * @author Dan */ public class GUIPanel extends JFrame { public GUIPanel() { initComponents(); } private void setOutputStream(boolean catchErrors) { System.setOut(aPrintStream); setVisible(true); requestFocus(); if (catchErrors) { System.setErr(aPrintStream); } } private void addTabs(JTabbedPane jTabbedPane1) { JPanel jPanel1 = new JPanel(); JPanel jPanel2 = new JPanel(); JPanel jPanel3 = new JPanel(); JPanel jPanel4 = new JPanel(); jTabbedPane1.add("Main", textArea1); jTabbedPane1.add("Commands", jPanel); jTabbedPane1.add("Rules", jPanel1); jTabbedPane1.add("Links", jPanel2); jTabbedPane1.add("Information", jPanel3); jTabbedPane1.add("Shutdown", jPanel4); setOutputStream(true); } @SuppressWarnings("unchecked") private void initComponents() { textArea1 = new java.awt.TextArea(); jTabbedPane1 = new javax.swing.JTabbedPane(); jMenuBar1 = new javax.swing.JMenuBar(); jMenu1 = new javax.swing.JMenu(); jMenu2 = new javax.swing.JMenu(); textArea1.setPreferredSize(new java.awt.Dimension(432, 343)); textArea1.getAccessibleContext().setAccessibleParent(jTabbedPane1); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("Evolution-X 639"); setBounds(new java.awt.Rectangle(0, 0, 400, 450)); setResizable(false); getContentPane().setLayout(new java.awt.FlowLayout()); addTabs(jTabbedPane1); getContentPane().add(jTabbedPane1); jMenu1.setText("File"); jMenuBar1.add(jMenu1); jMenu2.setText("Edit"); jMenuBar1.add(jMenu2); setJMenuBar(jMenuBar1); pack(); } public static void main(String args[]) { try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (ClassNotFoundException ex) { java.util.logging.Logger.getLogger(GUIPanel.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (InstantiationException ex) { java.util.logging.Logger.getLogger(GUIPanel.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { java.util.logging.Logger.getLogger(GUIPanel.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(GUIPanel.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new GUIPanel().setVisible(true); } }); } private JMenu jMenu1; private JMenu jMenu2; private JMenuBar jMenuBar1; private JTabbedPane jTabbedPane1; private TextArea textArea1; private JPanel jPanel = new JPanel(); private PrintStream aPrintStream = new PrintStream( new FilterOutputStream( new ByteArrayOutputStream())); } 

Devi redirect il stream di stampa a un stream di output che puoi controllare …

Questo è un esempio di concetto che ho sviluppato per un’applicazione a cui sto lavorando per lavoro. Lo usiamo per far apparire la console di output quando è in esecuzione sui siti degli utenti, in modo che possiamo vedere cosa viene inviato allo standard out … finché non abbiamo risolto il nostro log che è;)

Fondamentalmente mette un OutputStream personalizzato tra il stream di stampa e la console per catturare l’output, ma consente comunque di stampare il contenuto sulla console. Questo è utile se stai eseguendo il programma dalla riga di comando o IDE. Potresti mettere un interruttore per fermarlo se vuoi …

inserisci la descrizione dell'immagine qui

 public class TestRedirect { public static void main(String[] args) { new TestRedirect(); } public TestRedirect() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } CapturePane capturePane = new CapturePane(); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(capturePane); frame.setSize(200, 200); frame.setLocationRelativeTo(null); frame.setVisible(true); PrintStream ps = System.out; System.setOut(new PrintStream(new StreamCapturer("STDOUT", capturePane, ps))); System.out.println("Hello, this is a test"); System.out.println("Wave if you can see me"); } }); } public class CapturePane extends JPanel implements Consumer { private JTextArea output; public CapturePane() { setLayout(new BorderLayout()); output = new JTextArea(); add(new JScrollPane(output)); } @Override public void appendText(final String text) { if (EventQueue.isDispatchThread()) { output.append(text); output.setCaretPosition(output.getText().length()); } else { EventQueue.invokeLater(new Runnable() { @Override public void run() { appendText(text); } }); } } } public interface Consumer { public void appendText(String text); } public class StreamCapturer extends OutputStream { private StringBuilder buffer; private String prefix; private Consumer consumer; private PrintStream old; public StreamCapturer(String prefix, Consumer consumer, PrintStream old) { this.prefix = prefix; buffer = new StringBuilder(128); buffer.append("[").append(prefix).append("] "); this.old = old; this.consumer = consumer; } @Override public void write(int b) throws IOException { char c = (char) b; String value = Character.toString(c); buffer.append(value); if (value.equals("\n")) { consumer.appendText(buffer.toString()); buffer.delete(0, buffer.length()); buffer.append("[").append(prefix).append("] "); } old.print(c); } } } 

inserisci la descrizione dell'immagine quiinserisci la descrizione dell'immagine qui

Aggiornato con un esempio funzionante. Test su Windows 7, Java 6 e Mac OS Lion Java 7

La soluzione di MadProgrammer è davvero grandiosa e ho basato il mio sul suo. Tuttavia, come sottolineato da Loopkin, non tratta i caratteri speciali (per essere precisi, fallisce su ogni carattere non ASCII).

La soluzione di Loopkin non ha funzionato per me, ma alla fine ho trovato due soluzioni che hanno funzionato.

Soluzione 1: gestisce ogni carattere da 1 byte (fino a U + 00FF)

Questa semplice soluzione gestisce ogni carattere fino a U + 00FF (ogni carattere da 1 byte). Tutto è identico a MadProgrammer, tranne write() che è definito come:

 @Override public void write(int b) throws IOException { buffer.append(Character.toChars((b + 256) % 256)); if ((char) b == '\n') { textArea.append(str); textArea.setCaretPosition(textArea.getDocument().getLength()); buffer.delete(0, buffer.length()); } old.write(b); } 

Non ho inserito il prefisso, perché non ne avevo bisogno.

Soluzione 2: gestisce ogni object come output standard

Alla fine, ho deciso di includere tutti i personaggi, quindi ho finito per estendere direttamente PrintStream e anche PrintStream il prefisso / indent. Il problema è che non potevo ignorare il metodo privato write(String s) , quindi ho annullato tutti i metodi print() :

 public class PrintStreamCapturer extends PrintStream { private JTextArea text; private boolean atLineStart; private String indent; public PrintStreamCapturer(JTextArea textArea, PrintStream capturedStream, String indent) { super(capturedStream); this.text = textArea; this.indent = indent; this.atLineStart = true; } public PrintStreamCapturer(JTextArea textArea, PrintStream capturedStream) { this(textArea, capturedStream, ""); } private void writeToTextArea(String str) { if (text != null) { synchronized (text) { text.setCaretPosition(text.getDocument().getLength()); text.append(str); } } } private void write(String str) { String[] s = str.split("\n", -1); if (s.length == 0) return; for (int i = 0; i < s.length - 1; i++) { writeWithPotentialIndent(s[i]); writeWithPotentialIndent("\n"); atLineStart = true; } String last = s[s.length - 1]; if (!last.equals("")) { writeWithPotentialIndent(last); } } private void writeWithPotentialIndent(String s) { if (atLineStart) { writeToTextArea(indent + s); atLineStart = false; } else { writeToTextArea(s); } } private void newLine() { write("\n"); } @Override public void print(boolean b) { synchronized (this) { super.print(b); write(String.valueOf(b)); } } @Override public void print(char c) { synchronized (this) { super.print(c); write(String.valueOf(c)); } } @Override public void print(char[] s) { synchronized (this) { super.print(s); write(String.valueOf(s)); } } @Override public void print(double d) { synchronized (this) { super.print(d); write(String.valueOf(d)); } } @Override public void print(float f) { synchronized (this) { super.print(f); write(String.valueOf(f)); } } @Override public void print(int i) { synchronized (this) { super.print(i); write(String.valueOf(i)); } } @Override public void print(long l) { synchronized (this) { super.print(l); write(String.valueOf(l)); } } @Override public void print(Object o) { synchronized (this) { super.print(o); write(String.valueOf(o)); } } @Override public void print(String s) { synchronized (this) { super.print(s); if (s == null) { write("null"); } else { write(s); } } } @Override public void println() { synchronized (this) { newLine(); super.println(); } } @Override public void println(boolean x) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(char x) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(int x) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(long x) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(float x) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(double x) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(char x[]) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(String x) { synchronized (this) { print(x); newLine(); super.println(); } } @Override public void println(Object x) { String s = String.valueOf(x); synchronized (this) { print(s); newLine(); super.println(); } } } 

Ho rimosso l'aspetto Consumer per mantenerlo semplice, ma tutto ciò che è effettivamente necessario è qui. Ecco come ho usato questa class:

 System.setOut(new PrintStreamCapturer(logTextArea, System.out)); System.setErr(new PrintStreamCapturer(logTextArea, System.err, "[ERROR] ")); 

Mi piace la risposta di MadProgrammer ma non penso che funzioni per i caratteri UTF-8.

Invece farei di StreamCapturer estendere ByteArrayOutputStream e usarlo come implementazione di scrittura.

  @Override public void write(int b){ if ('\n' == (char) b) { consumer.appendText(toString()); reset(); } else { super.write(b); } old.write(b); } 

Sto saltando la parte del prefisso perché non ne ho bisogno nella mia implementazione. Grazie per il codice, è stato di grande aiuto!

Solo un aggiornamento del codice originale di MadProgrammer per NOOBS: passa un parametro JTextArea al costruttore, ad es

 new RedirectText(Main.window.textArea1);