Create SplashScreen to show file copy progress

4

I'm trying to create a splashscreen because when my application is open I take some time-consuming actions, like:

  • Copy files
  • Run an .exe

My Main looks like this:

import com.sun.javafx.application.LauncherImpl;

@SuppressWarnings("restriction")
public class Main 
{
   public static void main(String[] args) 
   {
      LauncherImpl.launchApplication(MyApplication.class, SplashScreenLoader.class, args);
   }
}

The class MyApplication calls my home screen of the program and the class SplashScreenLoader would be responsible for being my splash is like this:

import java.net.URL;

import javafx.application.Preloader;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class SplashScreenLoader extends Preloader {

    private Stage splashScreen;

    @Override
    public void start(Stage stage) throws Exception {
        URL arquivo = getClass().getResource("SplashScreen.fxml");
        Parent parent = FXMLLoader.load(arquivo);
        splashScreen = stage;
        splashScreen.setTitle("Iniciando..");
        splashScreen.setScene(new Scene(parent));
        splashScreen.setResizable(false);
        splashScreen.show();
        splashScreen.show();
    }


    @Override
    public void handleApplicationNotification(PreloaderNotification notification) {
        if (notification instanceof StateChangeNotification) {
            splashScreen.hide();
        }
    }

}

The controller of my fxml , its initialize method is responsible for copying my files, it has the following code snippet:

try
{
    this.lblTitle.setText(Confg.project);
    if(this.verifyArchives(Confg.origin, "php", Confg.pathPHP))
    {
        boolean start = false;
        do
        {
            try
            {
                this.runPHP(Confg.localhost);
                start = true;
            } catch (Exception e) { }
        }while(!start);
        this.verifyArchives(Confg.pathWWW + Confg.project, "www", Confg.pathWWW + Confg.project);
    }
}
catch (Exception e) { this.lblStatus.setText(e.getMessage()); }
The verifyArchives method is responsible for checking if the files already exist, and if it does not exist the copyAll method is called, passing parameters as the source and destination, and the label of my SplashScreen that will be responsible for displaying the status of the process.

public static boolean copyAll(File origin, File destiny, boolean overwrite, Label info) throws IOException, UnsupportedOperationException
{
    if (!destiny.exists())
        destiny.mkdir();

    if (!origin.isDirectory())
        throw new UnsupportedOperationException("Origem deve ser um diretório");

    if (!destiny.isDirectory())
        throw new UnsupportedOperationException("Destino deve ser um diretório");

    File[] files = origin.listFiles();
    for (int i = 0; i < files.length; ++i)
    {
        if (files[i].isDirectory())
            copyAll(files[i], new File(destiny + "\" + files[i].getName()), overwrite, info);
        else
        {
            System.out.println("Copiando arquivo: " + files[i].getName());
            info.setText("Copiando arquivo: " + files[i].getName());
            copy(files[i], new File(destiny + "\" + files[i].getName()), overwrite);
        }
    }
    return true;
}

At the end of the method I have a println and a setText that should transform the text of my label into the current status of the process. But when you start the program for the first time (that is when it will copy the files), println messages are displayed in the console, for example: " Copying file: blablabla.txt ". And just after copying all the files that my splash opens, with label with the message " Copying file: ultimo-file.txt".

The question is exactly how do I display splashscreen just before copying the files so that I can see the copy process in my splash?

    
asked by anonymous 18.06.2016 / 05:36

1 answer

3

I can not tell if your PreLoader is set correctly, mainly because of this:

import com.sun.javafx.application.LauncherImpl;

Normally, you use the launch of the Application itself.

Now, the one recommended to perform long tasks is to create a method that runs on a thread, and warn PreLoader when everything is right, something like:

public class MyApplication extends Application {

    Stage stage;
    BooleanProperty ready = new SimpleBooleanProperty(false);

    private void chamadaDemorada() {
        Task task = new Task<Void>() {
            @Override
            protected Void call() throws Exception {
                //por exemplo, a sua função que copia arquivos
                copyAll(origin, destiny, overwrite, info);
                // se quiser enviar o progresso                         
                notifyPreloader(new ProgressNotification(progresso));
                //e quando estiver pronto
                ready.setValue(Boolean.TRUE);
                notifyPreloader(new StateChangeNotification(
                    StateChangeNotification.Type.BEFORE_START));
                return null;
            }
        };
        new Thread(task).start();
    }

    @Override
    public void start(final Stage stage) throws Exception {
        chamadaDemorada();

        Parent root = FXMLLoader.load(getClass().getResource("FXMLdaApp.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);

        ready.addListener(new ChangeListener<Boolean>() {
            public void changed(
                ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
                if (Boolean.TRUE.equals(t1)) {
                    Platform.runLater(new Runnable() {
                        public void run() {
                            stage.show();
                        }
                    });
                }
            }
        });

    }
}

This method must be called from the start method of Application .

If you want to try other methods, I suggest checking the PreLoaders document.

    
25.06.2016 / 08:54