如何刷新Java的JTextArea? [英] How do I flush to Java's JTextArea?

查看:291
本文介绍了如何刷新Java的JTextArea?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用一个按钮写一个GUI。当用户单击按钮时,我想开始工作...消息立即出现在JTextArea中,并且完成。当工作完成时出现消息。 GUI包含一些形式的代码

I am writing a GUI with a button. When the user clicks the button, I would like a "Beginning work..." message to appear in a JTextArea immediately, and a "Finished." message to appear when the work is done. The GUI contains some code of the form

private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
    myJTextArea.append("Beginning work...\n");

    <more lines of code>

    myJTextArea.append("Finished.\n");
}

不幸的是,有没有办法将消息刷新JTextArea?在另一个论坛上,我看到人们提到为JTextArea输出运行单独的线程。

Unfortunately, neither message appears until the end. Is there a way to flush messages to JTextArea? On another forum, I saw people mention running a separate thread for the JTextArea output. Would some solution based on that be possible?

推荐答案

不幸的是,直到结束时才会显示消息。有没有办法将消息刷新JTextArea?在另一个论坛上,我看到提到为JTextArea输出运行单独的线程。基于这一点的一些解决方案是否可能?

Unfortunately, neither message appears until the end. Is there a way to flush messages to JTextArea? On another forum, I saw mention running a separate thread for the JTextArea output. Would some solution based on that be possible?

这与刷新JTextArea没有任何关系,确保你的代码遵循Swing线程规则。输出到JTextArea的长时间运行的代码应该在后台线程中调用,例如使用SwingWorker。然后它会间歇地将其结果输出到JTextArea,但确保在Swing事件线程上仔细这么做。如果你使用SwingWorker,可以使用publish / process方法对。

This has nothing to do with "flushing" the JTextArea, and all to do with making sure that your code follows Swing threading rules. The long running code that is outputting to the JTextArea should be called in a background thread such as with a SwingWorker. Then it would intermittently output its results to the JTextArea, but making sure to do so carefully on the Swing event thread. If you use a SwingWorker, this could be done using the publish/process method pair.

看看:教程:Swing中的并发

例如: / p>

For example:

import java.util.List;
import javax.swing.*;

public class SwingThreadingEg extends JPanel implements MyAppendable {
    private JTextArea area = new JTextArea(30, 50);

    public SwingThreadingEg() {
        JScrollPane scrollPane = new JScrollPane(area);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        add(scrollPane);
    }

    @Override
    public void append(String text) {
        area.append(text);
    }

    private static void createAndShowGui() {
        SwingThreadingEg mainPanel = new SwingThreadingEg();
        MyWorker myWorker = new MyWorker(mainPanel);
        // add a Prop Change listener here to listen for
        // DONE state then call get() on myWorker
        myWorker.execute();

        JFrame frame = new JFrame("SwingThreadingEg");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

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

class MyWorker extends SwingWorker<Void, String> {
    private static final long SLEEP_TIME = 500;
    private MyAppendable myAppendable;

    public MyWorker(MyAppendable myAppendable) {
        this.myAppendable = myAppendable;
    }

    @Override
    protected Void doInBackground() throws Exception {
        publish("Beginning Work");

        // simulate some long-running task:
        for (int i = 0; i < 20; i++) {
            publish("From SwingWorker: " + i);
            Thread.sleep(SLEEP_TIME);
        }
        publish("Finished!");
        return null;
    }

    @Override
    protected void process(List<String> chunks) {
        for (String text : chunks) {
            myAppendable.append(text + "\n");
        }
    }
}

interface MyAppendable {
    public void append(String text);
}

代码从我的代码改为从以前的类似问题

Code adapted from my code from an answer to a previous similar question.

如果你打算使用一个标准的Runnable和没有SwingWorker的后台线程,Lars建议你首先想实现一个Runnable而不是扩展线程,你必须最多的所有Swing调用都排队到事件线程,因此类似:

Note, if you're going to use a standard Runnable and a background Thread without a SwingWorker, as Lars recommends, you'll first of all want to implement a Runnable and not extend Thread, and you must take care that most all Swing calls are queued onto the event thread, thus something like:

@Override
public void actionPerformed(ActionEvent e) {
    textarea.append("Start...");
    new Thread(new Runnable(){
        @Override
        public void run() {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    textarea.append("End");
                }
            });
        }
    }).start();
}

这看起来有点复杂了所有嵌套的匿名内部类,事实上,这是为什么SwingWorker在这种情况下可以更好地工作的主要原因之一,因为使用的代码更简单,减少了创建未看见的错误的机会。

This looks a bit complicated what with all the nested anonymous inner classes, and in fact this is one of the main reasons why a SwingWorker may work better in this situation, since the code used is simpler, reducing the chances of creating unseen bugs.

这篇关于如何刷新Java的JTextArea?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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