2010-12-14 5 views
9

J'ai une classe (montrée ci-dessous) qui s'étend JPanel et contient un JTextPane. Je veux rediriger System.out et System.err à mon JTextPane. Ma classe ne semble pas fonctionner. Lorsque je l'exécute, il redirige les impressions du système, mais elles n'impriment pas sur mon JTextPane. S'il vous plaît aider!Rediriger System.out vers JTextPane

Remarque: Les appels sont uniquement redirigés lorsque l'application est lancée. Mais à tout moment après le lancement, les appels System.out ne sont pas redirigés vers le JTextPane. (Par exemple, si je place un System.out.prinln(); dans la classe, il sera appelé, mais s'il est placé dans un actionListener pour une utilisation ultérieure, il ne redirige pas).

public class OSXConsole extends JPanel { 
    public static final long serialVersionUID = 21362469L; 

    private JTextPane textPane; 
    private PipedOutputStream pipeOut; 
    private PipedInputStream pipeIn; 


    public OSXConsole() { 
     super(new BorderLayout()); 
     textPane = new JTextPane(); 
     this.add(textPane, BorderLayout.CENTER); 

     redirectSystemStreams(); 

     textPane.setBackground(Color.GRAY); 
     textPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 

    } 


    private void updateTextPane(final String text) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       Document doc = textPane.getDocument(); 
       try { 
        doc.insertString(doc.getLength(), text, null); 
       } catch (BadLocationException e) { 
        throw new RuntimeException(e); 
       } 
       textPane.setCaretPosition(doc.getLength() - 1); 
      } 
     }); 
    } 


    private void redirectSystemStreams() { 
     OutputStream out = new OutputStream() { 
     @Override 
     public void write(final int b) throws IOException { 
      updateTextPane(String.valueOf((char) b)); 
     } 

     @Override 
     public void write(byte[] b, int off, int len) throws IOException { 
      updateTextPane(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)); 
    } 


} 
+0

J'ai supprimé ma réponse car elle était erronée. – jjnguy

+0

Voyez-vous certains appels sont redirigés et d'autres pas? – jjnguy

+0

Seuls les appels provenant de la classe OSXConsole sont imprimés dans le JTextPane. Correction – Jakir00

Répondre

7

Canalisé ruisseaux me confondez toujours, ce qui est la raison pour laquelle ma solution Console message ne les utilise pas. Quoi qu'il en soit, voici ma tentative de console utilisant des flux canalisés. Un couple de différences:

a) il utilise un JTextArea car un JTextArea est plus efficace qu'un JTextPane pour juste afficher du texte. Bien sûr, si vous avez l'intention d'ajouter des attributs au texte, vous avez besoin d'un volet de texte.

b) cette solution utilise des threads. Je suis sûr que j'ai lu quelque part que c'était nécessaire pour empêcher le blocage de la sortie. Quoi qu'il en soit, cela fonctionne dans mon cas de test simple.

import java.io.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.text.*; 

public class Console implements Runnable 
{ 
    JTextArea displayPane; 
    BufferedReader reader; 

    private Console(JTextArea displayPane, PipedOutputStream pos) 
    { 
     this.displayPane = displayPane; 

     try 
     { 
      PipedInputStream pis = new PipedInputStream(pos); 
      reader = new BufferedReader(new InputStreamReader(pis)); 
     } 
     catch(IOException e) {} 
    } 

    public void run() 
    { 
     String line = null; 

     try 
     { 
      while ((line = reader.readLine()) != null) 
      { 
//    displayPane.replaceSelection(line + "\n"); 
       displayPane.append(line + "\n"); 
       displayPane.setCaretPosition(displayPane.getDocument().getLength()); 
      } 

      System.err.println("im here"); 
     } 
     catch (IOException ioe) 
     { 
      JOptionPane.showMessageDialog(null, 
       "Error redirecting output : "+ioe.getMessage()); 
     } 
    } 

    public static void redirectOutput(JTextArea displayPane) 
    { 
     Console.redirectOut(displayPane); 
     Console.redirectErr(displayPane); 
    } 

    public static void redirectOut(JTextArea displayPane) 
    { 
     PipedOutputStream pos = new PipedOutputStream(); 
     System.setOut(new PrintStream(pos, true)); 

     Console console = new Console(displayPane, pos); 
     new Thread(console).start(); 
    } 

    public static void redirectErr(JTextArea displayPane) 
    { 
     PipedOutputStream pos = new PipedOutputStream(); 
     System.setErr(new PrintStream(pos, true)); 

     Console console = new Console(displayPane, pos); 
     new Thread(console).start(); 
    } 

    public static void main(String[] args) 
    { 
     JTextArea textArea = new JTextArea(); 
     JScrollPane scrollPane = new JScrollPane(textArea); 

     JFrame frame = new JFrame("Redirect Output"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(scrollPane); 
     frame.setSize(200, 100); 
     frame.setVisible(true); 

     Console.redirectOutput(textArea); 
     final int i = 0; 

     Timer timer = new Timer(1000, new ActionListener() 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       System.out.println(new java.util.Date().toString()); 
       System.err.println(System.currentTimeMillis()); 
      } 
     }); 
     timer.start(); 
    } 
} 
7

Message Console classe fait pour vous.

Edit:

Voici une classe de test simple:

import java.io.*; 
import java.awt.*; 
import javax.swing.*; 
import javax.swing.event.*; 
import javax.swing.text.*; 

public class MessageConsoleTest 
{ 
    public static int counter; 

    public static void main(String[] args) 
     throws Exception 
    { 
     JTextComponent textComponent = new JTextPane(); 
     JScrollPane scrollPane = new JScrollPane(textComponent); 

     JFrame.setDefaultLookAndFeelDecorated(true); 
     JFrame frame = new JFrame("Message Console"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(scrollPane); 
     frame.setSize(400, 120); 
     frame.setVisible(true); 

     MessageConsole console = new MessageConsole(textComponent); 
     console.redirectOut(); 
     console.redirectErr(Color.RED, null); 

     Timer timer = new Timer(1000, new java.awt.event.ActionListener() 
     { 
      public void actionPerformed(java.awt.event.ActionEvent e) 
      { 
       System.out.println(new java.util.Date().toString()); 
      } 
     }); 
     timer.start(); 

     Thread.sleep(750); 

     Timer timer2 = new Timer(1000, new java.awt.event.ActionListener() 
     { 
      public void actionPerformed(java.awt.event.ActionEvent e) 
      { 
       System.err.println("Error Message: " + ++counter); 
      } 
     }); 
     timer2.start(); 
    } 
} 
+1

J'ai essayé ceci, mais cela ne semble pas fonctionner du tout. – Jakir00

+0

@Jacob, si vous avez un simple SSCCE (http://sscce.org) qui démontre que cela ne fonctionne pas, vous pouvez utiliser la page "Contactez-nous" du site pour m'envoyer du code à regarder. – camickr

+0

Cela fonctionne si vous l'utilisez correctement. Cependant, pour obtenir une sortie en direct, vous devrez mettre des tâches de longue durée sur un SwingWorker. – CaffeineToCode