6

編集:私は自分の質問を明確にするために投稿を編集しましたが、今では私自身、より理解が深まっています。

私は基本的に、タイトルが示すようにJTextArea、アプリケーションのタスクを実行しながら、GUIでコンソールを出力しようとしています。

これが私が現在行っていることです:

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

上記は、上記の出力ストリームに正常にリダイレクトされるため、GUIを更新するためにSystem.outイベントをにディスパッチします( )。EventQueueJTextArea

ここに問題があります:

現在invokeLater()、ドキュメントに記載されているようにwillを使用しています。

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

したがって、実際に実行したいのはrun()、EventQueue内の他のすべてを処理する前に、GUIの更新(呼び出し)を実行することです。

基本的にイベントをEventQueueに挿入することは可能ですか?または、誰かが私にこの分野のまともなチュートリアルを教えてもらえますか?

ありがとう、

4

5 に答える 5

11

次の例では、テキスト領域のあるフレームを作成し、System.out をそこにリダイレクトします。

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);
        }
    }
}
于 2013-02-05T11:52:57.800 に答える
5

あなたのエラーは、あなたがまだ私たちに示していない別の場所にあるに違いありません。これは、あなたのコードとほぼ同じコードで期待どおりに動作する非常に単純なデモです (マイナーな問題のみを修正しました)。

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();
            }
        });
    }
}
于 2013-02-05T15:22:13.883 に答える
3

使用する必要があるかもしれませんPipedOutputStream... ここで質問への回答を参照してください: How to redirect all console output to a Swing JTextArea/JTextPane with the right encoding?

基本的にこれが行うことは、System.outをバッファにリダイレクトすることです。そこから、プログラムは で出力された出力を読み取ることができますSystem.out。これはPiping

于 2013-02-05T11:46:52.110 に答える