尽管尝试正确的线程,JTextArea仍未实时更新

时间:2014-11-07 16:53:38

标签: java multithreading swing jtextarea

以下是另一个'如何让JTextArea实时更新'的问题。我已经阅读了现有的所有帖子,我认为我正确地将其解读。但是,我仍然遇到同样的问题 - 我的JTextArea在环路完成之前不会更新,然后在一次大爆炸中更新。有人可以看到我做错了吗?我看不到它。谢谢!

编辑:切换文本区域更新被调用的方法。但我仍然有同样的结果!

private void saveImagesToDisk() {

    textArea.append("\nPreparing to save photos to photos directory\n\n");

    for (MediaFeedData mfd : imagesMetaDataList) {
        try {
            String imageURL = mfd.getImages().getLowResolution().getImageUrl();
            final String filename = mfd.getId(); // just name the file using the image id from instagram
            System.out.println(filename);

            SaveImageFromUrl.saveImage(imageURL, filename, textArea);

        } catch (IOException e) {
            e.printStackTrace();

        }
    }

}

然后,在保存方法中,我有:

public class SaveImageFromUrl {

public static Boolean saveImage(final String imageUrl, String destinationFile, final JTextArea textArea) throws IOException {

    String directoryName = "photos";
    if (!makePhotosDirectory(directoryName, textArea)) {return false;}

    File file = new File(directoryName, destinationFile);
    URL url = new URL(imageUrl);
    InputStream is = url.openStream();
    OutputStream os = new FileOutputStream(file);

    byte[] b = new byte[2048];
    int length;

    while ((length = is.read(b)) != -1) {
        os.write(b, 0, length);
    }

    is.close();
    os.close();

    new Thread() {
        public void run() {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    textArea.append(imageUrl + " written to photos directory\n");
                }
            });
        }       
    }.start();


    return true;
}

1 个答案:

答案 0 :(得分:2)

for循环和下面方法中的代码都需要在后台线程中调用,这是你没有做到的。

if (SaveImageFromUrl.saveImage(imageURL, filename, textArea)) {

如果时间密集型代码不是在后台调用的代码,那么仅使用后台线程将无济于事。

考虑使用SwingWorker,比如......

   private void saveImagesToDisk() {
      textArea.append("\nPreparing to save photos to photos directory\n\n");

      final SwingWorker<Void, String> imageWorker = new SwingWorker<Void, String>() {
         @Override
         protected Void doInBackground() throws Exception {

            for (MediaFeedData mfd : imagesMetaDataList) {
               final String imageURL = mfd.getImages().getLowResolution().getImageUrl();
               final String filename = mfd.getId();
               System.out.println(filename);
               String textToPublish = "";
               if (SaveImageFromUrl.saveImage(imageURL, filename, textArea)) {
                  textToPublish = filename + " written to photos directory\n";
               } else {
                  textToPublish = filename + " not saved!\n";
               }

               // publish String so it can be used in the process method
               publish(textToPublish);
            }
            return null;
         }

         @Override
         protected void process(List<String> chunks) {
            // Strings sent to the EDT by the publish method
            // This called on the Swing event thread.
            for (String chunk : chunks) {
               textArea.append(chunk);
            }
         }
      };

      imageWorker.addPropertyChangeListener(new PropertyChangeListener() {

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
               try {
                  // need to call this on the event thread
                  // to catch any exceptions that have occurred int he Swing Worker
                  imageWorker.get();
               } catch (InterruptedException e) {
                  e.printStackTrace();
               } catch (ExecutionException e) {
                  // TODO catch exceptions buried in this guy
                  e.printStackTrace();
               }
            }
         }
      });

      // run our SwingWorker
      imageWorker.execute();
   }

有关详细信息,请阅读Concurrency in Swing