阐明新线程的启动和停止时间和位置

时间:2018-02-06 03:14:01

标签: java javafx

我按照在线教程为我的JavaFX应用程序构建了一个启动画面。这是SplashController文件:

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();

        }

    }

} 
}

我试图诠释我对线程如何在这里工作的理解,并希望你能为我澄清以下内容是否正确或回答问题:

1)如果我从不创建任何扩展thread或创建任何新Runnable()对象的新类,我可以假设我的JavaFX项目中的所有内容都在单个JavaFX应用程序线程上运行;

2)当我创建内部类SplashScreen extends Thread并在其上调用start()时,我是否创建了第二个线程?因此,我有两个线程 - 常规JavaFX应用程序线程和SplashScreen线程;

3)当我然后调用Platform.runLater( new Runnable() { .... } )时,是否在JavaFX应用程序线程,SplashScreen线程或新的第三个线程中设置了新阶段,FXML和控制器?

4)当我调用splashRoot.getScene().getWindow().hide()时,是否结束了SplashScreen线程?或者该线程是否继续new Runnable()调用的Platform.runLater()

1 个答案:

答案 0 :(得分:2)

  

1)如果我从不创建任何扩展线程或新的类   创建任何新的Runnable()对象,我可以假设一切都在   我的JavaFX项目在单个JavaFX应用程序线程上运行;

只要您不调用任何内容(例如来自其他API)就行了。

  

2)当我创建内部类SplashScreen扩展Thread并调用时   start()就可以了,我创建了第二个线程吗?所以我有两个   线程 - 常规JavaFX应用程序线程和SplashScreen   螺纹;

是。请注意SplashScreen在需要处理UI内容时使用Platform.runLater()

  

3)当我然后调用Platform.runLater(new Runnable(){....})时   它在JavaFX应用程序中设置了新阶段,FXML和控制器   线程,SplashScreen线程,还是新的第三个线程?

调用Platform.runLater()的代码位于第二个线程上。 Runnable内的Platform.runLater()对象是一个放在JavaFX Application Thread的“队列”中的对象,线程在完成它正在做或需要做的任何事情之后将运行(即呈现UI等)

  

4)当我调用splashRoot.getScene()。getWindow()。hide()时,这样做结束了吗   SplashScreen线程?或者是那个线程继续新的   由Platform.runLater()调用的Runnable()?

它只是关闭托管启动画面的窗口。 线程结束,因为它是线程必须执行的Runnable中的最后一行代码。线程结束是因为在将Runnable放到JavaFX应用程序线程队列之后没有别的事情要做。

摘要

  1. 您创建了一个显示启动画面的窗口。
  2. 在控制器的构造函数中,您创建了另一个线程。
  3. 在那个帖子中,你让它(那个新线程)睡了3000ms。
  4. 唤醒后,您将返回JavaFX Application Thread,然后在那里加载新内容并打开新窗口,并关闭启动画面。