How to use thread in JavaFX?

2

Before the main scenario of my JavaFX application appears, I want a class containing a presentation to appear; I can not use the sleep method. A% blank% appears and then the class containing the presentation. I want the presentation window to appear and then the main window. How to do this?

public static Stage WINDOWS;

@Override
public void start(Stage primaryStage) throws Exception {

    Parent root = new FirstLayout().portal();

    Scene scene = new Scene(root);

    WINDOWS = primaryStage;

    WINDOWS.setTitle("Memory Game");

    WINDOWS.setScene(scene);

    WINDOWS.show();

     try {
            //InputThread: nome do cenário que quero que apareça
            //inputThread: nome do método que traz o layout do cenário; 

        WINDOWS.setScene(new Scene(new InputThread().inputThread()));
        Thread.sleep(3000);

        } catch (InterruptedException ex) {} 

}
public static void main(String [] args){launch(args);}
}
    
asked by anonymous 23.04.2015 / 23:27

1 answer

1

I do not know if this is what you want, but tai:

import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

/** Example of displaying a splash page for a standalone JavaFX application */
public class TaskBasedSplash extends Application {
  private Pane splashLayout;
  private ProgressBar loadProgress;
  private Label progressText;
  private Stage mainStage;
  private static final int SPLASH_WIDTH = 676;
  private static final int SPLASH_HEIGHT = 227;

  public static void main(String[] args) throws Exception { launch(args); }

  @Override public void init() {
    ImageView splash = new ImageView(new Image("http://fxexperience.com/wp-content/uploads/2010/06/logo.png"));
    loadProgress = new ProgressBar();
    loadProgress.setPrefWidth(SPLASH_WIDTH - 20);
    progressText = new Label("Will find friends for peanuts . . .");
    splashLayout = new VBox();
    splashLayout.getChildren().addAll(splash, loadProgress, progressText);
    progressText.setAlignment(Pos.CENTER);
    splashLayout.setStyle("-fx-padding: 5; -fx-background-color: cornsilk; -fx-border-width:5; -fx-border-color: linear-gradient(to bottom, chocolate, derive(chocolate, 50%));");
    splashLayout.setEffect(new DropShadow());
  }

  @Override public void start(final Stage initStage) throws Exception {
    final Task<ObservableList<String>> friendTask = new Task() {
      @Override protected ObservableList<String> call() throws InterruptedException {
        ObservableList<String> foundFriends = 
          FXCollections.<String>observableArrayList();
        ObservableList<String> availableFriends = 
          FXCollections.observableArrayList("Fili", "Kili", "Oin", "Gloin", "Thorin", "Dwalin", "Balin", "Bifur", "Bofur", "Bombur", "Dori", "Nori", "Ori");

        updateMessage("Finding friends . . .");
        for (int i = 0; i < availableFriends.size(); i++) {
          Thread.sleep(400);
          updateProgress(i+1, availableFriends.size());
          String nextFriend = availableFriends.get(i);
          foundFriends.add(nextFriend);
          updateMessage("Finding friends . . . found " + nextFriend);
        }
        Thread.sleep(400);
        updateMessage("All friends found.");

        return foundFriends;
      }
    };

showSplash(initStage, friendTask);
new Thread(friendTask).start();
showMainStage(friendTask.valueProperty());
  }

  private void showMainStage(ReadOnlyObjectProperty<ObservableList<String>> friends) {
    mainStage = new Stage(StageStyle.DECORATED);
    mainStage.setTitle("My Friends");
    mainStage.setIconified(true);
    mainStage.getIcons().add(new     Image("http://cdn1.iconfinder.com/data/icons/Copenhagen/PNG/32/people.png"));

    final ListView<String> peopleView = new ListView<>();
    peopleView.itemsProperty().bind(friends);

    mainStage.setScene(new Scene(peopleView));
   mainStage.show();
  }

  private void showSplash(final Stage initStage, Task task) {
    progressText.textProperty().bind(task.messageProperty());
    loadProgress.progressProperty().bind(task.progressProperty());
    task.stateProperty().addListener(new ChangeListener<Worker.State>() {
      @Override public void changed(ObservableValue<? extends Worker.State> observableValue,     Worker.State oldState, Worker.State newState) {
        if (newState == Worker.State.SUCCEEDED) {
          loadProgress.progressProperty().unbind();
          loadProgress.setProgress(1);
          mainStage.setIconified(false);
         initStage.toFront();
          FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2),         splashLayout);
          fadeSplash.setFromValue(1.0);
          fadeSplash.setToValue(0.0);
          fadeSplash.setOnFinished(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent actionEvent) {
              initStage.hide();
            }
          });
          fadeSplash.play();
        } // todo add code to gracefully handle other task states.
      }
    });

Scene splashScene = new Scene(splashLayout);
initStage.initStyle(StageStyle.UNDECORATED);
final Rectangle2D bounds = Screen.getPrimary().getBounds();
initStage.setScene(splashScene);
initStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2);
initStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2);
initStage.show();
  }
}

Explaining what it does:

Image1:

Herethelink: link

This code creates a SplashScreen that is something like what you said, first it shows a presentation screen that in the image is a screen to load.

And after loading it shows this:

Image2:

Explainingthecode:

Inthefirstimageyouloadascreen,whichisanimageandaProgressBar,thisisdoneintheshowSplashmethod,whichiswhereyouturnontheprogressbarwiththeTask,TaskistheclasswhereyoucantobecreatedaThread,thiscanbeexplainedinthislink: link , But summarizing JavaFX only takes care of the layout and does not have another thread for other executions.

In the code, a stage is used to create both the opening screen (image1) and creating the main screen (image2).

The showMainStage method is the layout of the image2.

The init method is the layout of the image1.

And the start is where the Task (Thread) will be started, the time will be determined (Below the progressbar the lines of the FXCollections... are shown):

        for (int i = 0; i < availableFriends.size(); i++) {
          Thread.sleep(400);
          updateProgress(i+1, availableFriends.size());
          String nextFriend = availableFriends.get(i);
          foundFriends.add(nextFriend);
          updateMessage("Finding friends . . . found " + nextFriend);
        }
        Thread.sleep(400);

And started the other methods:

showSplash(initStage, friendTask);
new Thread(friendTask).start();
showMainStage(friendTask.valueProperty());

I hope I have helped.

There is a class called Service , this class can separate the two screens.

The code:

import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.concurrent.Worker;
import javafx.concurrent.WorkerStateEvent;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.ProgressBar;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;

/** Example of displaying a splash page for a standalone JavaFX application */
public class TaskBasedSplash extends Application {
  private Pane splashLayout;
  private ProgressBar loadProgress;
  private Label progressText;
  private Stage mainStage;
  private static final int SPLASH_WIDTH = 676;
  private static final int SPLASH_HEIGHT = 227;

  public static void main(String[] args) throws Exception { launch(args); }

      @Override 
      public void init() {
            ImageView splash = new ImageView(new Image("http://fxexperience.com/wp-content/uploads/2010/06/logo.png"));
            loadProgress = new ProgressBar();
            loadProgress.setPrefWidth(SPLASH_WIDTH - 20);
            progressText = new Label("Will find friends for peanuts . . .");
            splashLayout = new VBox();
            splashLayout.getChildren().addAll(splash, loadProgress, progressText);
            progressText.setAlignment(Pos.CENTER);
            splashLayout.setStyle("-fx-padding: 5; -fx-background-color: cornsilk; -fx-border-width:5; -fx-border-color: linear-gradient(to bottom, chocolate, derive(chocolate, 50%));");
            splashLayout.setEffect(new DropShadow());
          }

      @Override 
      public void start(final Stage initStage) throws Exception {
          Service<ObservableList<String>> service = new Service<ObservableList<String>>(){ 
            @Override
            protected Task<ObservableList<String>> createTask(){
                  return new Task<ObservableList<String>>() {
                  @Override 
                  protected ObservableList<String> call() throws InterruptedException {
                    ObservableList<String> foundFriends = 
                      FXCollections.<String>observableArrayList();
                    ObservableList<String> availableFriends = 
                      FXCollections.observableArrayList("Fili", "Kili", "Oin", "Gloin", "Thorin", "Dwalin", "Balin", "Bifur", "Bofur", "Bombur", "Dori", "Nori", "Ori");

                    updateMessage("Finding friends . . .");
                    for (int i = 0; i < availableFriends.size(); i++) {
                      Thread.sleep(400);
                      updateProgress(i+1, availableFriends.size());
                      String nextFriend = availableFriends.get(i);
                      foundFriends.add(nextFriend);
                      updateMessage("Finding friends . . . found " + nextFriend);
                    }
                    Thread.sleep(400);
                    updateMessage("All friends found.");

                    return foundFriends;
                  }
                };
            }
          };

        service.start();
        service.setOnRunning((WorkerStateEvent event) -> {
            showSplash(initStage, service); 
        });
        service.setOnSucceeded((WorkerStateEvent event) -> {
            try {
                showMainStage(service.valueProperty());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

      }

      private void showMainStage(ReadOnlyObjectProperty<ObservableList<String>> service) throws InterruptedException {
        mainStage = new Stage(StageStyle.DECORATED);
        mainStage.setTitle("My Friends");
        mainStage.getIcons().add(new     Image("http://cdn1.iconfinder.com/data/icons/Copenhagen/PNG/32/people.png"));

        final ListView<String> peopleView = new ListView<>();
        peopleView.itemsProperty().bind(service);

        mainStage.setScene(new Scene(peopleView));
        mainStage.show();
      }

      private void showSplash(final Stage initStage, Service<ObservableList<String>> service) {
        progressText.textProperty().bind(service.messageProperty());
        loadProgress.progressProperty().bind(service.progressProperty());
        service.stateProperty().addListener(new ChangeListener<Worker.State>() {
          @Override public void changed(ObservableValue<? extends Worker.State> observableValue,     Worker.State oldState, Worker.State newState) {
            if (newState == Worker.State.SUCCEEDED) {
              loadProgress.progressProperty().unbind();
              loadProgress.setProgress(1);
              initStage.toFront();
              FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2),         splashLayout);
              fadeSplash.setFromValue(1.0);
              fadeSplash.setToValue(0.0);
              fadeSplash.setOnFinished((asd) -> initStage.hide());
              fadeSplash.play();
            }
          }
        });

        Scene splashScene = new Scene(splashLayout);
        initStage.initStyle(StageStyle.UNDECORATED);
        final Rectangle2D bounds = Screen.getPrimary().getBounds();
        initStage.setScene(splashScene);
        initStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2);
        initStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2);
        initStage.show();
  }
}

The changes I made were in methods: start , showSplash and showMainStage .

Task<ObservableList<String>> was replaced with return new Task<... within a method created within the Service class.

The mainStage.setIcofield(boolean) was removed so as not to minimize the Stage .

And then the methods that called Task were replaced with Service .

It separates the two screens when the second screen is placed inside service.setOnSucceeded(... of method start , and the first screen in sercice.setOnRunning(... .

If the initial screen disappearance time is large you can change the number from FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2), splashLayout); to Duration.serconds .

I hope I have helped.

    
11.05.2015 / 23:25