Reputation: 1098
I followed an online tutorial for building a splash screen for my JavaFX application. Here is the SplashController file:
package splash;
import java.io.IOException;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
* SplashController controls the Splash.FXML file. This is the initial software display. After a
* designated amount of time, the MainMenu.FXML is run.
*
*/
public class SplashController {
@FXML
private StackPane splashRoot;
@FXML
private ImageView splashImage;
/**
* Called after all @FXML annotated members have been injected. Starts a new thread "SplashScreen()".
*/
@FXML void initialize() {
new SplashScreen().start(); //Start SplashScreen thread.
}
/**
* Inner class that extends thread. Displays the splash screen for a designated amount of time then loads
* MainMenu.FXML, sets a new stage, and displays the main menu. Hides the splash screen.
*
*/
class SplashScreen extends Thread {
@Override
public void run() {
try {
splashImage.fitWidthProperty().bind( splashRoot.widthProperty() ); // binds the image to the rootPane width.
Thread.sleep( 3000 ); // puts the thread (SplashScreen) to sleep in order to allow the splash to display long enough.
Platform.runLater( new Runnable() { // Forces the main menu scene to load onto the SplashScreen thread when it is available.
@Override
public void run() {
FXMLLoader loader = new FXMLLoader( getClass().getResource( "../mainMenu/MainMenu.FXML" ) ); // Places MainMenu.FXML into the loader.
Stage stage = new Stage(); // Creates a new stage.
try {
stage.setScene( new Scene( loader.load() ) ); // Sets the scene using the root node of the loaded FXML document.
} catch ( IOException e ) {
e.printStackTrace();
}
stage.setResizable(false); // Prevents user from resizing the window.
stage.setTitle( "Test" ); // Sets the stage title.
stage.show(); // Displays the stage.
splashRoot.getScene().getWindow().hide(); // Hides the splash screen and presumably ends the SplashScreen thread.
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I have tried to annotate my understanding of how the threads are working here and was hoping you could either clarify for me if the following are correct or answer the question:
1) If I was to never create any new classes that extend thread
or create any new Runnable()
objects, I could assume that everything in my JavaFX project is running on a single JavaFX application thread;
2) When I create the inner class SplashScreen extends Thread
and call start()
on it, am I creating a second thread? So I therefore have two threads - the regular JavaFX application thread and the SplashScreen
thread;
3) When I then call Platform.runLater( new Runnable() { .... } )
does it set that new stage, FXML, and controller in the JavaFX application thread, the SplashScreen thread, or yet a new third thread?
4) When I call splashRoot.getScene().getWindow().hide()
, does that end the SplashScreen thread? Or is that thread continuing with the new Runnable()
that was called by Platform.runLater()
?
Upvotes: 0
Views: 177
Reputation: 8363
1) If I was to never create any new classes that extend thread or create any new Runnable() objects, I could assume that everything in my JavaFX project is running on a single JavaFX application thread;
That is true as long you don't call anything (e.g. from other API) that does that.
2) When I create the inner class SplashScreen extends Thread and call start() on it, am I creating a second thread? So I therefore have two threads - the regular JavaFX application thread and the SplashScreen thread;
Yes. Do note that SplashScreen
uses Platform.runLater()
when it needs to handle UI stuff.
3) When I then call Platform.runLater( new Runnable() { .... } ) does it set that new stage, FXML, and controller in the JavaFX application thread, the SplashScreen thread, or yet a new third thread?
The code calling Platform.runLater()
is on the second thread. The Runnable
object inside Platform.runLater()
is an object that is put inside JavaFX Application Thread's "queue," which the thread will run after it has completed whatever it is doing or needs to do (i.e. render UI etc).
4) When I call splashRoot.getScene().getWindow().hide(), does that end the SplashScreen thread? Or is that thread continuing with the new Runnable() that was called by Platform.runLater()?
It simply closes the window that is hosting your splash screen. The thread ends because it is the last line of code in the . The thread ends because there is nothing else to do after placing the Runnable
that the thread has to do Runnable
onto the JavaFX Application Thread queue.
Upvotes: 2