1
I need to create a progress indicator so that the user has a sense that the program is running something from behind.
Briefly I want to upload images to a TilePane
grid gallery style, however when I try to upload these images it can sometimes take what makes the program appear to be stuck.
The gallery is based on this link: https://stackoverflow.com/a/27184788/3792998
Code:
import Controller.FxmlSplashLoadingController;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.TilePane;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TestExample extends Application {
Stage stage;
TilePane tile;
@Override
public void start(Stage primaryStage) throws Exception {
stage = primaryStage;
ScrollPane root = new ScrollPane();
tile = new TilePane();
root.setStyle("-fx-background-color: DAE6F3;");
tile.setPadding(new Insets(15, 15, 15, 15));
tile.setHgap(15);
//loading example
Stage stageLoader = createLoaderSplashBar();
//stageLoader.show();
stageLoader.setAlwaysOnTop(true);
// here runs the JavaFX thread
// Boolean as generic parameter since you want to return it
Task task = new Task<Void>() {
@Override
protected Void call() throws Exception {
Platform.runLater(new Runnable() {
@Override
public void run() {
taskLongLoadImg();
}
});
return null;
}
};
task.setOnRunning((e) -> stageLoader.show());
task.setOnSucceeded((e) -> {
stageLoader.hide();
//Boolean returnValue = task.get();
// process return value again in JavaFX thread
});
task.setOnFailed((e) -> {
// eventual error handling by catching exceptions from task.get()
});
new Thread(task).start();
root.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); // Horizontal
root.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED); // Vertical scroll bar
root.setFitToWidth(true);
root.setContent(tile);
primaryStage.setWidth(Screen.getPrimary().getVisualBounds().getWidth());
primaryStage.setHeight(Screen.getPrimary().getVisualBounds()
.getHeight());
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public Stage createLoaderSplashBar() {
Stage newStage = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/View/FxmlSplashLoading.fxml"));
Parent root = null;
try {
root = (Parent) fxmlLoader.load();
} catch (IOException ex) {
System.out.println("Error - Loading FxmlSplashLoading.fxml");
Logger.getLogger(TestExample.class.getName()).log(Level.SEVERE, null, ex);
}
FxmlSplashLoadingController controller = fxmlLoader.<FxmlSplashLoadingController>getController();
controller.setStage(newStage);
controller.setController(controller); // guardar o proprio controller para depois poder inserir texto na label
newStage.setScene(new Scene(root));
// newStage.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
// if (!isNowFocused) {
// System.out.println("windows closed .......");
// newStage.hide();
// }
// });
newStage.initStyle(StageStyle.UNDECORATED);
newStage.initModality(Modality.WINDOW_MODAL);
// newStage.show();
return newStage;
}
public void taskLongLoadImg(){
String path = "C:\\Users\\jsantos1991\\Pictures\\ImagesTeste";
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (final File file : listOfFiles) {
System.out.println("file:" +file.getName());
file.setReadOnly();
ImageView imageView;
imageView = createImageView(file);
tile.getChildren().addAll(imageView);
try {
Thread.sleep(300); //
} catch (InterruptedException ex) {
Logger.getLogger(TestExample.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
private ImageView createImageView(final File imageFile) {
// DEFAULT_THUMBNAIL_WIDTH is a constant you need to define
// The last two arguments are: preserveRatio, and use smooth (slower)
// resizing
ImageView imageView = null;
try {
final Image image = new Image(new FileInputStream(imageFile), 150, 0, true,
true);
imageView = new ImageView(image);
imageView.setFitWidth(150);
imageView.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if(mouseEvent.getButton().equals(MouseButton.PRIMARY)){
if(mouseEvent.getClickCount() == 2){
try {
BorderPane borderPane = new BorderPane();
ImageView imageView = new ImageView();
Image image = new Image(new FileInputStream(imageFile));
imageView.setImage(image);
imageView.setStyle("-fx-background-color: BLACK");
imageView.setFitHeight(stage.getHeight() - 10);
imageView.setPreserveRatio(true);
imageView.setSmooth(true);
imageView.setCache(true);
borderPane.setCenter(imageView);
borderPane.setStyle("-fx-background-color: BLACK");
Stage newStage = new Stage();
newStage.setWidth(stage.getWidth()-400);
newStage.setHeight(stage.getHeight()-400);
newStage.setTitle(imageFile.getName());
Scene scene = new Scene(borderPane,Color.BLACK);
newStage.setScene(scene);
newStage.show();
newStage.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (!isNowFocused) {
System.out.println("focus out .......");
newStage.hide();
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
});
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
return imageView;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Briefly I wanted you to show an indicator of progress and that it was possible to see the TilePane
adding images/ to be updated from behind.
This article should give you the knowledge you need to implement this, but take a look also at the class documentation Task, that has some "little secrets" about cancelling the Task and about using
Platform.runLater(...)
.– Douglas
Thanks @Douglas I’ll read the article...
– jsantos1991