问题
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