How to use thread in Javafx?

Asked

Viewed 1,874 times

2

Before appearing the main scenario of my Javafx application, I want a class containing a presentation to appear; I’m unable to use the method sleep. A stage blank and then the class containing the presentation. I want the presentation window to appear and then the main one. 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);}
}

1 answer

1


I don’t know if that’s 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 she does:

Image1:

inserir a descrição da imagem aqui

Here the link: http://www.fxexperience.com/

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

And after you click it shows this:

Imagem2:

inserir a descrição da imagem aqui

Explaining the code:

In the first image a screen is loaded, which is an image and a Progressbar, this is done in the method showSplash, which is where you "connect" the progress bar with Task, Task is the class in which a Thread can be created, this can be explained in this link: http://aprendendo-javafx.blogspot.com.br/2014/08/threads-e-javafx.html , But summarizing Javafx only takes care of the layout and has no other thread for other runs.

In the code is used a Stage to create both the aperture screen(imagem1) and to create the main screen(imagem2).

The method showMainStage is the layout of the imagem2.

The method init is the layout of the image1.

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

        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 initiated the other methods:

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

I hope I’ve 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 the methods: start,showSplash and showMainStage.

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

Was removed the mainStage.setIcofield(boolean) not to minimize the Stage.

And then the methods they called the Task were replaced by Service.

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

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

I hope I helped.

  • I edited the answer, sorry for the delay.

  • In this case, you are minimizing the main stage at a certain time to show another and then maximize it; but I want the main stage to be shown only after the second stage is gone.

  • In Swing you could still do it with a setVisible(false), in Javafx, you can in place of setIconfiet(false) for setOpacity(0.0) and it gets (or should spin) invisible, if it doesn’t work it also has in place mainStage.close() and then on before initializing the method showMainStage()(or in place of setIconfiet(true)) the mainStage.show(). In case I find another better solution I put.

  • If you find it, enter the code, okay? Thanks!

  • Edited Code.

  • Did it work? Got the mark right.

  • Thank you, Lucas... right!

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.