Show background process status in JTextArea

我们两清 提交于 2019-12-13 18:55:30

问题


Is there any way to write text in JTextArea about background process. I have one button on screen. When user click on that button, some process is started. I want to show ongoing status of that process on screen which is in Text area. After doing textArea.append("Some status") I use to call textArea.repaint() but this not work for me.

Should I need to implement my own Thread for this?


回答1:


You simply can use a SwingWorker, where you really doesn't have to worry about performing the periodic task on the Event Dispatcher Thread. You simply will call publish() inside doInBackground() method to append the specified text to JTextArea, which will invoke process() and perform the whole task on Event Dispatcher Thread automatically.

Have a look at this working example :

import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

public class LoadingImage {

    private JPanel contentPane;
    private JTextArea logArea;
    private JLabel imageLabel;
    private ImageIcon[] images;
    private JButton startStopButton;
    private String[] path;
    private int counter;

    private Timer timer;

    private ActionListener timerAction = 
                            new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            counter %= path.length;
            imageLabel.setIcon(images[counter++]);
        }
    };

    private ActionListener buttonAction = 
                            new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            if (timer.isRunning()) {
                startStopButton.setText("Start");
                timer.stop();
            }
            else {
                startStopButton.setText("Stop");
                timer.start();
            }
        }
    };

    public LoadingImage() {
        imageLabel = new JLabel("Nothing to display yet...", JLabel.CENTER);
        images = new ImageIcon[5];
        path = new String[] {
            "http://i.imgur.com/922oehL.gif",
            "http://i.imgur.com/2Fim5t4.gif",
            "http://i.imgur.com/jJKlCiI.gif",
            "http://i.imgur.com/0KuZuGl.gif",
            "http://i.imgur.com/evuKoI5.gif"
        };
        counter = 0;
    }

    private void displayGUI() {
        JFrame frame = new JFrame("Loading Image Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new JPanel(new BorderLayout(5, 5));
        JPanel centerPanel = new JPanel(new GridLayout(1, 2, 5, 5));
        logArea = new JTextArea(10, 10);
        JScrollPane logScroller = new JScrollPane();
        logScroller.setViewportView(logArea);

        centerPanel.add(logScroller);
        centerPanel.add(imageLabel);
        contentPane.add(centerPanel, BorderLayout.CENTER);

        startStopButton = new JButton("Stop");
        startStopButton.addActionListener(buttonAction);
        contentPane.add(startStopButton, BorderLayout.PAGE_END);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        new BackgroundTask().execute();
        timer = new Timer(1000, timerAction);
        timer.start();
    }

    private class BackgroundTask extends SwingWorker<ImageIcon[], String> {
        @Override
        protected ImageIcon[] doInBackground() {
            ImageIcon[] images = new ImageIcon[path.length];
            for (int i = 0; i < path.length; i++)
            {
                try {
                images[i] = new ImageIcon(ImageIO.read(new URL(path[i])));
                }catch(Exception e) {e.printStackTrace();}
                publish(String.format("Loaded : %s%n", path[i]));
            }

            return images;
        }

        @Override
        protected void process(java.util.List<String> messages) {
            for (String message : messages)
                logArea.append(message);
        }

        @Override
        protected void done() {
            try {
                images = get();             
            } catch(Exception e) {e.printStackTrace();}
        }
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new LoadingImage().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}



回答2:


The textArea.repaint() call is completely superfluous. After a call to append, repaint is automatically called, so you don't need to call it.

Here's an example:

Process p = ...; // start the process somehow
final BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
new Thread() {
    private String line;
    public void run() {
        while ((line = br.readLine()) != null) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    textArea.append(line);
                }
            });
        }
    }
}.start();

This code should be run when the button is clicked.



来源:https://stackoverflow.com/questions/18031956/show-background-process-status-in-jtextarea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!