我创建了一个类作为加载器,用于在后台Thread中加载图像,并将其添加到JavaFX Application中,

我的问题是,尽管该类可用作Task,但它会导致JavaFX Apllication在图像加载期间冻结,并在完成后再次正常工作,

加载程序类代码:

import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

public class Loader{
    private String type     = "";
    private String url      = "";
    private ImageView image = new ImageView();

    private class LoaderService extends Service{
        @Override
        protected Task createTask() {
            return new LoaderTask();
        }
    }

    private class LoaderTask extends Task{
        @Override
        protected Object call() throws Exception {
            new LoaderClass();

            return null;
        }
    }

    private String getType(){
        return this.type;
    }

    private String getUrl(){
        return this.url;
    }

    public Loader type(String type){
        this.type = type;
        return this;
    }

    public Loader url(String url){
        this.url = url;
        return this;
    }

    public ImageView getImage(){
        return this.image;
    }

    public Loader build(){
        new LoaderTask().run();
        return this;
    }

    private class LoaderClass{
        public LoaderClass(){
            switch(getType()){
                case "image":
                    this.loadImage(getUrl());
                break;
            }
        }

        private void loadImage(String url){
            try{
                getImage().setImage(new Image(url));
            }catch(Exception ex){
                System.out.println("Ex"+ex.getMessage());
            }
        }
    }
}

调用加载程序以获取来自外部类的图像以将其添加到主JavaFX Window内的示例:
StackPane Pane = new StackPane();

ImageView Icon1 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/1.png")
                                    .build()
                                    .getImage();

ImageView Icon2 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/2.png")
                                    .build()
                                    .getImage();

ImageView Icon3 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/3.png")
                                    .build()
                                    .getImage();

ImageView Icon4 = new NinjaLoader()
                                    .type("image")
                                    .url("http://localhost/images/4.png")
                                    .build()
                                    .getImage();
Pane.getChildren().addAll(Icon1,Icon2,Icon3,Icon4);

那么,导致这些冻结的代码中有什么错误呢?

谢谢 ,

最佳答案

问题是您通过调用runRunnable方法在同一线程中运行任务:

new LoaderTask().run();

通常的做法是在一个线程中运行它(简单):
Thread th = new Thread(new LoaderTask());
th.setDaemon(true);
th.start();

或将其发送到线程池(需要更多工作)。 More on this in the related Oracle docs...

更新

如果仍然冻结:
  • 确保您不执行任何I/O操作,即读取FX线程中的文件或资源,因为这会阻止UI更新,从而导致冻结。 FX线程是您可以从中更新UI属性的线程。
  • 尝试在单独的线程中加载资源,并通过运行Platform.runLater将场景中的部分/全部加载到场景中后立即更新场景图。
  • 09-16 05:17