Java 在执行长程序期间,作为控制台输出动态更新JTextArea?

Java 在执行长程序期间,作为控制台输出动态更新JTextArea?,java,swing,Java,Swing,假设一个程序执行大量的方法。例如,在安装软件安装方法时,您希望跟踪JtextArea中的进度。我正在执行一个需要20秒或更长时间才能执行的程序。我想在文本区域中显示输出,更新间隔为50到100毫秒。我如何实现它? 我使用了计时器,但它在程序执行后更新了文本区域,而不是在执行期间,java线程冻结了GUI temp1.redirectOutput( textArea ); final int i = 0; Timer timer = new Timer(1000, new A

假设一个程序执行大量的方法。例如,在安装软件安装方法时,您希望跟踪JtextArea中的进度。我正在执行一个需要20秒或更长时间才能执行的程序。我想在文本区域中显示输出,更新间隔为50到100毫秒。我如何实现它? 我使用了计时器,但它在程序执行后更新了文本区域,而不是在执行期间,java线程冻结了GUI

   temp1.redirectOutput( textArea );
   final int i = 0;

    Timer timer = new Timer(1000, new ActionListener() {
        public void actionPerformed(ActionEvent e) {

            String str = "";
            int i = 0;
            while(i < 3000){
                str = "aaaa";
                System.out.println(str);
                i++;
            }
            System.out.println( new java.util.Date().toString() );
            System.err.println( System.currentTimeMillis() );
        }
    });
    timer.start();
temp1.重定向输出(textArea);
最终积分i=0;
计时器计时器=新计时器(1000,新ActionListener(){
已执行的公共无效操作(操作事件e){
字符串str=“”;
int i=0;
而(i<3000){
str=“aaaa”;
系统输出打印项次(str);
i++;
}
System.out.println(新java.util.Date().toString());
System.err.println(System.currentTimeMillis());
}
});
timer.start();

使用
SwingWorker
获取您可能缓存到可管理块中的信息,并使用worker发布这些信息

请查看以了解更多详细信息

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel implements LongTimeConsumer {

        private JTextArea ta;

        public TestPane() {
            setLayout(new BorderLayout());
            ta = new JTextArea(10, 20);
            add(new JScrollPane(ta));
            JButton btn = new JButton("Start");
            add(btn, BorderLayout.SOUTH);
            btn.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    btn.setEnabled(false);
                    LongTimeWorker worker = new LongTimeWorker(TestPane.this);
                    worker.addPropertyChangeListener(new PropertyChangeListener() {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            LongTimeWorker worker = (LongTimeWorker) evt.getSource();
                            if ("state".equals(evt.getPropertyName())) {
                                btn.setEnabled(worker.isDone());
                            }
                        }
                    });
                    worker.execute();
                }
            });
        }

        @Override
        public void contentUpdated(List<String> values) {
            for (String text : values) {
                ta.append(text);
                ta.append("\n");
            }
            ta.setCaretPosition(ta.getDocument().getLength());
        }

    }

    public interface LongTimeConsumer {
        public void contentUpdated(List<String> values);
    }

    public class LongTimeWorker extends SwingWorker<List<String>, List<String>> {

        private LongTimeConsumer consumer;

        public LongTimeWorker(LongTimeConsumer consumer) {
            this.consumer = consumer;
        }

        @Override
        protected List<String> doInBackground() throws Exception {
            List<String> total = new ArrayList<>(1000);
            List<String> values = new ArrayList<>(100);
            for (int index = 0; index < 1000; index++) {
                values.add("Some more text " + index);
                if (index % 100 == 0) {
                    total.addAll(values);
                    publish(values);
                    values = new ArrayList<>(100);
                }
                Thread.sleep(1);
            }
            if (!values.isEmpty()) {
                    total.addAll(values);
                    publish(values);
            }
            return total;
        }

        @Override
        protected void process(List<List<String>> chunks) {
            for (List<String> values : chunks) {
                consumer.contentUpdated(values);
            }
        }

    }
}
导入java.awt.BorderLayout;
导入java.awt.EventQueue;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.util.ArrayList;
导入java.util.List;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JScrollPane;
导入javax.swing.JTextArea;
导入javax.swing.SwingWorker;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
公开课考试{
公共静态void main(字符串[]args){
新测试();
}
公开考试(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
例如printStackTrace();
}
JFrame=新JFrame(“测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(newtestpane());
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
});
}
公共类TestPane扩展JPanel实现LongTimeConsumer{
私人住宅区;
公共测试窗格(){
setLayout(新的BorderLayout());
ta=新的JTextArea(10,20);
添加(新的JScrollPane(ta));
JButton btn=新JButton(“开始”);
添加(btn,BorderLayout.SOUTH);
btn.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件e){
btn.setEnabled(false);
LongTimeWorker=新的LongTimeWorker(TestPane.this);
worker.addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
LongTimeWorker=(LongTimeWorker)evt.getSource();
if(“state”.equals(evt.getPropertyName())){
btn.setEnabled(worker.isDone());
}
}
});
worker.execute();
}
});
}
@凌驾
已更新公共void内容(列表值){
用于(字符串文本:值){
ta.追加(文本);
ta.追加(“\n”);
}
ta.setCaretPosition(ta.getDocument().getLength());
}
}
公共接口长期消费者{
更新的公共无效内容(列表值);
}
公共类LongTimeWorker扩展SwingWorker{
私人长期消费者;
公共长期工作者(长期消费者){
这个。消费者=消费者;
}
@凌驾
受保护列表doInBackground()引发异常{
列表总数=新阵列列表(1000);
列表值=新的ArrayList(100);
对于(int-index=0;index<1000;index++){
添加(“更多文本”+索引);
如果(索引%100==0){
总计.addAll(值);
出版(价值观);
值=新的ArrayList(100);
}
睡眠(1);
}
如果(!values.isEmpty()){
总计.addAll(值);
出版(价值观);
}
返回总数;
}
@凌驾
受保护的无效进程(列表块){
for(列表值:块){
消费者。内容更新(价值);
}
}
}
}

如果您使用的是
System.out
,您也可以执行类似或的操作。您可以在此处看到完整的代码。使用
.append(String str)
方法如何?@AndriyRymar这是最简单的方法。不,那不行,明白了。当我遇到同样的问题时,我只是使用了一些结构,比如
List
StringBuilder
,并在那里管理所有新行。然后,当我必须在UI上显示日志数据时,我只需将
JTextArea
中的内容替换为我的结构的最新内容,而使用SwingWorker