Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JTextArea未实时更新,尽管尝试了正确的线程_Java_Multithreading_Swing_Jtextarea - Fatal编程技术网

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

Java JTextArea未实时更新,尽管尝试了正确的线程,java,multithreading,swing,jtextarea,Java,Multithreading,Swing,Jtextarea,下面是另一个“如何获得实时更新的JTextArea”问题。我已经阅读了所有现有的帖子,我认为我的思路是正确的。然而,我仍然有同样的问题——我的JTextArea直到循环完成后才更新,然后在一次大爆炸中更新。有人能看出我做得不对吗?我看不见。谢谢 编辑:切换文本区域以更新被调用的方法。但我还是有同样的结果 private void saveImagesToDisk() { textArea.append("\nPreparing to save photos to photos dire

下面是另一个“如何获得实时更新的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();

        }
    }

}
然后,在save方法中,我有:

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;
}

下面方法中的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();
   }
private void saveImagesToDisk(){
textArea.append(“\n准备将照片保存到照片目录\n\n”);
最终SwingWorker imageWorker=新SwingWorker(){
@凌驾
受保护的Void doInBackground()引发异常{
用于(MediaFeedData mfd:imagesMetaDataList){
最终字符串imageURL=mfd.getImages().getLowResolution().getImageUrl();
最终字符串文件名=mfd.getId();
System.out.println(文件名);
字符串textToPublish=“”;
if(SaveImageFromUrl.saveImage(imageURL、文件名、文本区域)){
textToPublish=filename+“已写入照片目录\n”;
}否则{
textToPublish=filename+“未保存!\n”;
}
//发布字符串,以便在process方法中使用它
发布(textToPublish);
}
返回null;
}
@凌驾
受保护的无效进程(列表块){
//通过发布方法发送到EDT的字符串
//这将调用Swing事件线程。
for(字符串块:块){
textArea.append(块);
}
}
};
addPropertyChangeListener(新的PropertyChangeListener(){
@凌驾
公共作废属性更改(属性更改事件evt){
if(evt.getNewValue()==SwingWorker.StateValue.DONE){
试一试{
//需要在事件线程上调用它
//捕获Swing Worker中发生的任何异常
get();
}捕捉(中断异常e){
e、 printStackTrace();
}捕获(执行例外){
//要抓住埋在这家伙身上的例外
e、 printStackTrace();
}
}
}
});
//管理我们的SwingWorker
execute();
}

有关更多详细信息,请阅读。

您的线程太乱了。为什么要创建一个新线程来使用
SwingUtilities.invokeAndWait
?这段代码的哪一部分需要很长时间来处理,
saveImage
调用?它们都不是特别慢。我还尝试了
invokeLater
(这似乎运行得快了一点),但即使我删除了关于Swing输出的所有内容,循环运行得也快得可以接受。速度不是问题——让文本区域在每次迭代中更新是关键。尤其是如果我正在下载数百个图像,是的,正是由于使用for循环和saveImage方法,导致Swing事件线程无法正常工作。更多信息,请参阅下面答案中的信息。谢谢,气垫船。我还尝试用一个新的线程来包装调用器。这为什么不能解决问题呢?非常感谢。它可以工作,但我现在的问题是它运行速度慢了10倍。这正常吗?@usr55410:从正确开始,然后是快速+1用于
SWingWorker