System.out.println to JTextArea

旧时模样 提交于 2019-12-29 05:38:06

问题


EDIT: I have edited the post to clarify my question, now I myself, have more understanding.

I am essentially, as the title says, attempting to output console to my JTextArea in my GUI, whilst performing the tasks of the application.

Here is what I am currently doing:

public class TextAreaOutputStream extends OutputStream
{

    private final JTextArea textArea;

    private final StringBuilder sb = new StringBuilder();

    public TextAreaOutputStream(final JTextArea textArea)
    {
        this.textArea = textArea;
    }

    @Override
    public void flush()
    {
    }

    @Override
    public void close()
    {
    }

    @Override
    public void write(int b) throws IOException
    {

        if (b == '\r')
            return;

        if (b == '\n')
        {
            final String text = sb.toString() + "\n";
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    textArea.append(text);
                }
            });
            sb.setLength(0);
        }
        sb.append((char) b);
    }
}

The above will successfully re-direct System.out to my output stream above and therefore despatch an event to the EventQueue to update my GUI (JTextArea).

Here is the issue:

Currently using invokeLater() will as it says on the docs:

Causes runnable to have its run method called in the dispatch thread of the EventQueue. This will happen after all pending events are processed.

So what I actually want to do is perform my update to the GUI (call run()) before processing everything else in the EventQueue.

Is it possible to inject an event essentially into my EventQueue? Or can somebody point me to an decent tutorial on this area?

thanks,


回答1:


The following example creates frame with text area and redirects System.out to it:

import java.awt.BorderLayout;
import java.awt.Container;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class JTextAreaOutputStream extends OutputStream
{
    private final JTextArea destination;

    public JTextAreaOutputStream (JTextArea destination)
    {
        if (destination == null)
            throw new IllegalArgumentException ("Destination is null");

        this.destination = destination;
    }

    @Override
    public void write(byte[] buffer, int offset, int length) throws IOException
    {
        final String text = new String (buffer, offset, length);
        SwingUtilities.invokeLater(new Runnable ()
            {
                @Override
                public void run() 
                {
                    destination.append (text);
                }
            });
    }

    @Override
    public void write(int b) throws IOException
    {
        write (new byte [] {(byte)b}, 0, 1);
    }

    public static void main (String[] args) throws Exception
    {
        JTextArea textArea = new JTextArea (25, 80);

        textArea.setEditable (false);

        JFrame frame = new JFrame ("stdout");
        frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        Container contentPane = frame.getContentPane ();
        contentPane.setLayout (new BorderLayout ());
        contentPane.add (
            new JScrollPane (
                textArea, 
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
            BorderLayout.CENTER);
        frame.pack ();
        frame.setVisible (true);

        JTextAreaOutputStream out = new JTextAreaOutputStream (textArea);
        System.setOut (new PrintStream (out));

        while (true)
        {
            System.out.println ("Current time: " + System.currentTimeMillis ());
            Thread.sleep (1000L);
        }
    }
}



回答2:


Your error must lie somewhere else that you haven't shown us yet. Here is a very simple demo that works as expected with almost the same code as yours (I only fixed minor issues):

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TextAreaOutputStream extends OutputStream {

    private final JTextArea textArea;

    private final StringBuilder sb = new StringBuilder();

    public TextAreaOutputStream(final JTextArea textArea) {
        this.textArea = textArea;
    }

    @Override
    public void flush() {
    }

    @Override
    public void close() {
    }

    @Override
    public void write(int b) throws IOException {

        if (b == '\r') {
            return;
        }

        if (b == '\n') {
            final String text = sb.toString() + "\n";

            textArea.append(text);
            sb.setLength(0);
        } else {
            sb.append((char) b);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame(TextAreaOutputStream.class.getSimpleName());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                JTextArea ta = new JTextArea(24, 80);
                System.setOut(new PrintStream(new TextAreaOutputStream(ta)));
                frame.add(new JScrollPane(ta));
                frame.pack();
                frame.setVisible(true);
                System.out.println("Textarea console initiated");
                Timer t = new Timer(1000, new ActionListener() {

                    int count = 1;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        System.out.println("Outputting line " + count++ + " to the console. Working properly, no?");
                    }
                });
                t.start();
            }
        });
    }
}



回答3:


You might need to use PipedOutputStream... see the answers to the question here: How to redirect all console output to a Swing JTextArea/JTextPane with the right encoding?

Basically what this does is, it redirects the System.out to a buffer, from which, the program can read the output printed with System.out. This is called Piping




回答4:


If you want to see scrolling effect in Text Area, then instead of appending the output, you can put the new text in beginning. Example:

HttpURLConnection con = (HttpURLConnection) (new URL(url[0]).openConnection());
con.setInstanceFollowRedirects(false);
con.connect();
int responseCode = con.getResponseCode();
String location = con.getHeaderField("Location");
textArea.setText(url[0] +"," +responseCode+"," +location+"\n"+textArea.getText()); //new text is prefixed to the existing text
textArea.update(textArea.getGraphics());



回答5:


I found a very simple, albeit possibly not the fastest or best way to do this. It is, however, very simple and if you're as lazy as I am, then it works nicely.

JTextArea output = new JTextArea();
PrintStream out = new PrintStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
    output.append(""+(char)(b & 0xFF));
}
});
System.setOut(out);
System.out.println("TEST");


来源:https://stackoverflow.com/questions/14706674/system-out-println-to-jtextarea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!