【问题标题】:System.out.println to JTextAreaSystem.out.println 到 JTextArea
【发布时间】:2013-01-20 07:54:05
【问题描述】:

编辑:我已经编辑了帖子以澄清我的问题,现在我自己有了更多的理解。

正如标题所说,我基本上是在尝试在我的 GUI 中将控制台输出到我的JTextArea,同时执行应用程序的任务。

这是我目前正在做的事情:

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

上面将成功地将System.out 重定向到我上面的输出流,因此向EventQueue 发送一个事件以更新我的GUI (JTextArea)。

问题来了:

目前使用 invokeLater() 将如文档所述:

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

所以我真正想做的是在处理 EventQueue 中的所有其他内容之前对 GUI 进行更新(调用 run())。

是否可以将事件本质上注入到我的 EventQueue 中?或者有人可以指点我这方面的一个不错的教程吗?

谢谢,

【问题讨论】:

  • “上述解决方案的工作原理是我将系统输出到我的 JTextArea,但是当我尝试在 actionPerformed() 中执行此操作时,我没有得到任何输出。” 你确定你通过了所有那些 if's 吗?没有充分的理由为什么一个 System.out 调用会起作用而另一个失败

标签: java swing user-interface jtextarea


【解决方案1】:

您可能需要使用 PipedOutputStream... 在此处查看问题的答案: How to redirect all console output to a Swing JTextArea/JTextPane with the right encoding?

基本上,它的作用是将System.out 重定向到一个缓冲区,程序可以从中读取使用System.out 打印的输出。这叫Piping

【讨论】:

    【解决方案2】:

    以下示例创建带有文本区域的框架并将 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);
            }
        }
    }
    

    【讨论】:

    • 嗯我的方法有什么问题?我在这里只能看到你刚刚重新创建了我的解决方案?你能指出它在哪里解决了我的问题吗?
    • Initial Thread 上睡觉没有错,但应该在 EDT 上构建 GUI 组件。
    • 您的方法有几个小问题,即您将每个'\n' 输出两次,但没有任何可能导致您描述的问题。你确定!"".equals(targetFile.getText())checkBox.isSelected() 都是真的吗?
    【解决方案3】:

    您的错误一定存在于您尚未向我们展示的其他地方。这是一个非常简单的演示,可以使用与您的代码几乎相同的代码(我只修复了小问题):

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

    【讨论】:

    • 问题是我自己对invokeLater()的愚蠢和误解。我的解决方案正在工作,但不是我想要的,即我的 GUI 已更新,但直到处理完 EventQueue 中的所有其他内容之后 - 即上面我的 sn-p 中的 ...。这不是我想要的。
    • @buymypies 顺便说一句,JTextArea.append 是线程安全的,因此无需将其包装在 invokeLater() 中。
    • 请查看我对我的问题的编辑,希望我已经更清楚地说明了我想要做什么。
    • @buymypies 1) 无需将JTextArea.append 包装在invokeLater() 中。 2) 如果您正在考虑在 EventQueue 上重新排序事件,请忘记它(这并不难):这只是意味着您在某处有错误的设计。如果您需要执行冗长的操作,请不要在 EDT 上执行它们,而是使用 SwingWorker 来实现。
    【解决方案4】:

    如果您想在文本区域中看到滚动效果,那么您可以将新文本放在开头,而不是附加输出。 示例:

    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】:

      我发现做到这一点的最佳方法非常简单,而且看起来效果很好。我已经使用了多年,没有任何问题。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 2011-07-25
        • 1970-01-01
        • 2017-05-25
        • 2012-05-16
        相关资源
        最近更新 更多