我创建了一个类作为加载器,用于在后台线程中加载图像,将它们添加到JavaFX应用程序中,
我的问题是,虽然这个类可以作为一个任务,但它会导致JavaFX Apllication在图像加载过程中冻结,并在完成后再正常工作,
Loader类代码:
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窗口中的示例:
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);
那么我的代码中导致这些冻结的错误是什么?
谢谢,
答案 0 :(得分:20)
您根本不需要管理线程来在后台线程中加载图像:Image构造函数有一个标志来执行此操作。只是做
ImageView icon1 = new ImageView(new Image("http://localhost/images/1.png", true));
等
答案 1 :(得分:4)
问题是您通过调用run
的{{1}}方法在同一个线程中运行您的任务:
Runnable
通常的做法是在线程(简单)中运行它:
new LoaderTask().run();
或将其发送到线程池(更多工作)。 More on this in the related Oracle docs...
<强>更新强>
如果它仍然冻结:
Thread th = new Thread(new LoaderTask());
th.setDaemon(true);
th.start();
时将部分/全部内容加载到内存中后立即更新。