Java将系统输出重定向到jtext区域,直到计算完成才更新 [英] Java redirected system output to jtext area, doesnt update until calculation is finished

查看:64
本文介绍了Java将系统输出重定向到jtext区域,直到计算完成才更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有将系统输出重定向到jtext区域的代码,但是直到代码运行完毕,该jtextarea才会更新.如何修改代码以在运行时实时更新jtextarea?

I have code that redirects system output to a jtext area, but that jtextarea doesnt update until the code is finished running. How do I modify the code to make the jtextarea update in real time during runtime?

private void updateTextArea(final String text) {
        SwingUtilities.invokeLater(new Runnable() {
          public void run() {
            consoleTextAreaInner.append(text);
          }
        });
      }
private void redirectSystemStreams() {
      OutputStream out = new OutputStream() {
        @Override
        public void write(int b) throws IOException {
          updateTextArea(String.valueOf((char) b));
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
          updateTextArea(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));
    }    

其余的代码主要只是一个按钮的动作监听器:

The rest of the code is mainly just an actionlistener for a button:

private void updateButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
    // TODO add your handling code here:
    String shopRoot = this.shopRootDirTxtField.getText();
    String updZipPath = this.updateZipTextField.getText();
    this.mainUpdater = new ShopUpdater(new File(shopRoot), updZipPath);
    this.mainUpdater.update();
}

该update()方法开始在文件系统上复制+粘贴文件的过程,在此过程中,使用system.out.println提供有关程序当前所在位置的最新状态,以了解如何还有更多文件要复制.

That update() method begins the process of copying+pasting files on the file system and during that process uses system.out.println to provide an up-to-date status on where the program is currently at in reference to how many more files it has to copy.

推荐答案

很难100%地确定发生了什么问题,因为我们看不到很多关键的相关代码,但是很有可能您遇到了Swing线程问题.您需要在后台线程中读取流,然后在Swing事件线程EDT上调用对文本区域的更新.否则,您将在等待流读取的同时绑定EDT,从而完全冻结您的GUI. SwingWorker会很好地工作.考虑在每次遇到新行时发布到JTextArea.

It's hard to tell with 100% assuredly what is going wrong, as there's a lot of critical involved code that we're not seeing, but there's a good chance that you're running into a Swing threading issue. You need to read the stream in a background thread and then call your update to text area method on the Swing event thread, the EDT. Otherwise you'll tie up the EDT while waiting for the stream to read, completely freezing your GUI. A SwingWorker would work well. Consider publishing to the JTextArea each time a new line is encountered.

例如:

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class MyRedirectStream {

   private JTextArea textArea;

   public MyRedirectStream(JTextArea gui) {
      this.textArea = gui;
   }

   public void redirect() {
      System.setOut(new PrintStream(new MyOutStream(), true));
      System.setErr(new PrintStream(new MyOutStream(), true));      
   }

   private class MyOutStream extends OutputStream {
      private static final int MAX_LENGTH = 1600;
      private StringBuilder sb = new StringBuilder(MAX_LENGTH + 100);

      @Override
      public void write(int b) throws IOException {
         sb.append((char)b);
         if (sb.length() > MAX_LENGTH) {
            sendToTextArea(sb.toString());
            sb = new StringBuilder();
         }
      }

      @Override
      public void flush() throws IOException {
         sendToTextArea(sb.toString());
         sb = new StringBuilder();
         super.flush();
      }
      private void sendToTextArea(final String text) {
         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               textArea.append(text);
            }
         });
      }

   }   
}

和:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class StreamToTextArea2 {
   public static void main(String[] args) {
      final TextPanel gui = new TextPanel();
      final MyRedirectStream myRedirectStream = new MyRedirectStream(
            gui.getTextarea());
      myRedirectStream.redirect();

      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            final JFrame frame = new JFrame("Redirect");
            JButton showTextBtn = new JButton(new AbstractAction("Show Text") {

               @Override
               public void actionPerformed(ActionEvent arg0) {
                  JFileChooser fileChooser = new JFileChooser();
                  int result = fileChooser.showOpenDialog(frame);
                  if (result == JFileChooser.APPROVE_OPTION) {
                     gui.clearText();
                     final File file = fileChooser.getSelectedFile();
                     new Thread(new Runnable() {
                        public void run() {
                           try {
                              Scanner scan = new Scanner(file);
                              while (scan.hasNextLine()) {
                                 System.out.println(scan.nextLine());
                              }
                           } catch (FileNotFoundException e) {
                              e.printStackTrace();
                           }

                        }
                     }).start();
                  }
               }
            });
            JButton clearTextBtn = new JButton(
                  new AbstractAction("Clear Text") {

                     @Override
                     public void actionPerformed(ActionEvent e) {
                        gui.clearText();
                     }
                  });
            JPanel btnPanel = new JPanel();
            btnPanel.add(clearTextBtn);
            btnPanel.add(showTextBtn);

            frame.getContentPane().add(gui);
            frame.getContentPane().add(btnPanel, BorderLayout.SOUTH);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

         }
      });

   }
}


import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

class TextPanel extends JPanel {
   private JTextArea textarea = new JTextArea(20, 40);

   public TextPanel() {
      setLayout(new BorderLayout());
      JScrollPane scrollPane = new JScrollPane(textarea);
      scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
      add(scrollPane);
   }

   public JTextArea getTextarea() {
      return textarea;
   }

   public void clearText() {
      textarea.setText("");
   }

}

这篇关于Java将系统输出重定向到jtext区域,直到计算完成才更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆