java 将 System.out 重定向到 JTextPane

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4443878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:24:26  来源:igfitidea点击:

Redirecting System.out to JTextPane

javaswing

提问by Jakir00

I have a class (shown below) that extends JPaneland contains a JTextPane. I want to redirect System.outand System.errto my JTextPane. My class does not seem to work. When I run it, it does redirect the system prints, but they do not print to my JTextPane. Please help!

我有一个类(如下所示),它扩展JPanel并包含一个JTextPane. 我想重定向System.outSystem.errJTextPane。我的课似乎不起作用。当我运行它时,它会重定向系统打印,但它们不会打印到我的JTextPane. 请帮忙!

Note:The calls are only redirected when the application launches. But any time after launch, the System.outcalls are not redirected to the JTextPane. (ie, if I place a System.out.prinln();in the class, it will be called, but if it is placed in a actionListenerfor later use, it does not redirect).

注意:调用仅在应用程序启动时重定向。但是在启动后的任何时候,System.out调用都不会重定向到JTextPane. (即,如果我System.out.prinln();在类中放置 a ,它将被调用,但如果将其放置在 a 中actionListener供以后使用,则不会重定向)。

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));
    }


}

采纳答案by camickr

Piped streams always confuse me, which is why my Message Console solution doesn't use them. Anyway here is my attempt at a console using piped streams. A couple of differences:

管道流总是让我感到困惑,这就是我的消息控制台解决方案不使用它们的原因。无论如何,这是我在使用管道流的控制台上的尝试。几个不同点:

a) it uses a JTextArea because a JTextArea is more efficient than a JTextPane for just displaying text. Of course if you intend to add attributes to the text then you need a text pane.

a) 它使用 JTextArea,因为 JTextArea 比仅显示文本的 JTextPane 更有效。当然,如果您打算向文本添加属性,那么您需要一个文本窗格。

b) this solution uses Threads. I'm sure I read somewhere that this was necessary to prevent blocking of the output. Anyway it works in my simple test case.

b) 此解决方案使用线程。我确定我在某处读到过,这是防止阻塞输出所必需的。无论如何,它适用于我的简单测试用例。

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();
    }
}

回答by camickr

Message Consoleclass does this for you.

Message Console类会为您执行此操作。

Edit:

编辑:

Here is a simple test class:

这是一个简单的测试类:

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();
    }
}

回答by eniel.rod

In the following linkyou can find the MessageConsole class that someone mentioned. I implemented a software and used this solution and it works perfect for me. I used the Netbeans design tool, so the code regarding the visual appearance of the JTextPane is a bit cumbersome, so I'm not going to place it here.

在以下链接中,您可以找到有人提到的 MessageConsole 类。我实现了一个软件并使用了这个解决方案,它非常适合我。我用的是Netbeans的设计工具,所以关于JTextPane的视觉外观的代码有点繁琐,这里就不放了。


JTextPane jTextPane = new JTextPane();

MessageConsole console = new MessageConsole(jTextPane);
/*
This parameters are optional, but if you are looking for a solution with JTextPane it is because you need them, at least color.
*/
console.redirectErr(Color.RED, null);
console.redirectOut();

//some event
private void jButton1ActionPerformed(ActionEvent evt) {
    /*
    In this event I execute a function of my business.
    I put it in a thread so that it does not block the graphical interface.
    There are many calls to System.out.println() and System.err.println()
    */
    BusinessClass bc = new BusinessClass();
    Runnable runnable = () -> {
        bc.someBusinessFn();
    };
    thread = new Thread(runnable);
    thread.start();
}

//My main method
public static void main(String args[]) {
        /* Create and display the GUI */
        EventQueue.invokeLater(() -> {
            new MyJFrame().setVisible(true);
        });
}

Edit

编辑

Sorry, I did not realize that in the response similar to this, they had put the link to the MessageConsole class. I didn't see it and I also wanted to show my solution.

抱歉,我没有意识到在与此类似的响应中,他们已经放置了 MessageConsole 类的链接。我没有看到它,我也想展示我的解决方案。