1
package htmlconsole;

import java.awt.BorderLayout;

public class HTMLConsole extends JFrame {

    private JPanel contentPane;
    private JTextPane textPane;

    public class Interceptor extends PrintStream
    {
        public Interceptor(OutputStream out)
        {
            super(out,true);
        }
        @Override
        public void print(String s)
        {
            super.print(s);
            textPane.setText(textPane.getText()+s);
        }

        @Override 
        public void println(String s)
        {
            super.println(s);
            textPane.setText(textPane.getText()+"\n<br>");
        }       
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    HTMLConsole frame = new HTMLConsole();
                    frame.setVisible(true);

                    System.out.println("Hello");

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public HTMLConsole() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 300);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        JTextPane textPane = new JTextPane();
        textPane.setEditable(false);
        textPane.setContentType("text/html");
        textPane.setText("");

        contentPane.add(textPane, BorderLayout.CENTER);

        //redirect stream
        PrintStream interceptor = new Interceptor(System.out);
        System.setOut(interceptor);
    }
}

输出:

Hellojava.lang.NullPointerException
    at console.Console$Interceptor.print(Console.java:29)
    at java.io.PrintStream.println(Unknown Source)
    at console.Console$Interceptor.println(Console.java:35)
    at console.Console$1.run(Console.java:47)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$000(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

我应该如何纠正这个程序?异常被抛出在未使用的“打印”方法中,这非常令人困惑!

更新:

替换JTextPane textPane = new JTextPane();为后异常消失textPane = new JTextPane();,但现在窗口内没有显示任何内容。在此处输入图像描述

4

3 回答 3

3

您可以使用 swing 的 MVC 功能来实现您的要求。由于 JTextPane 具有文档模型,因此您应该考虑使模型适应流。

public class DocumentPrintStream extends PrintStream {

    public DocumentPrintStream(Document document, OutputStream delegateStream) {
        super(delegateStream);
        this.document = document;
    }

    @Override
    public void print(String string) {
        int offset = document.getLength();
        try {
            document.insertString(offset, string, null);
        } catch (BadLocationException e) {
        }
        super.print(string); // write to the delegate stream
    }
}

public Console() {
    ...
    JTextPane textPane = new JTextPane();
    contentPane.add(textPane, BorderLayout.CENTER);

    // redirect stream
    Document document = textPane.getDocument();
    DocumentPrintStream documentPrintStream = new DocumentPrintStream(
            document, System.out);
    System.setOut(documentPrintStream );
}

它还有一个好处是您可以在DocumentPrintStream基于Document模型的每个组件中重用 。

例如:

  • JEdi​​torPane
  • 文本区域
  • JTextField
  • 文本窗格
于 2013-07-13T14:13:54.523 回答
3

您的构造函数调用

JTextPane textPane = new JTextPane(); // local variable declaration and initialization

而不是打电话

this.textPane = new JTextPane()

因此textPane,拦截器使用的字段为空。

另请注意,正如堆栈跟踪所示,super.println()调用print(). 这将导致传递给 println() 的每个字符串都被附加到文本窗格两次。

于 2013-07-13T14:05:12.550 回答
2

textPaneConsole. 代替

JTextPane textPane = new JTextPane();

textPane = new JTextPane();
于 2013-07-13T14:03:47.453 回答