如何在启动画面后显示主舞台

时间:2013-06-08 18:56:37

标签: javafx-2 javafx javafx-8

我想修改此代码:

public class test extends Application
{

    private Pane splashLayout;
    private ProgressBar loadProgress;
    private Label progressText;
    private Stage mainStage;
    private static final int SPLASH_WIDTH = 600;
    private static final int SPLASH_HEIGHT = 200;

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

    @Override
    public void init()
    {
        ImageView splash = new ImageView(getClass().getResource("/images/splash.png").toExternalForm());
        loadProgress = new ProgressBar();
        loadProgress.setPrefWidth(SPLASH_WIDTH + 20);
        progressText = new Label("All modules are loaded.");
        splashLayout = new VBox();
        splashLayout.getChildren().addAll(splash, loadProgress, progressText);
        progressText.setAlignment(Pos.CENTER);
        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("Network Module", "User Module", "User Interface", "User Controls");

                updateMessage("Loading Modules . . .");
                for (int i = 0; i < availableFriends.size(); i++)
                {
                    Thread.sleep(900);
                    updateProgress(i + 1, availableFriends.size());
                    String nextFriend = availableFriends.get(i);
                    foundFriends.add(nextFriend);
                    updateMessage("Loading Modules . . . Loading " + nextFriend);
                }
                Thread.sleep(500);
                updateMessage("All Modules are loaded.");

                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("Loading Modules");
        //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();
    }
}

你能告诉我如何在启动画面完成加载时修改代码以显示主舞台吗?在此示例中,同时显示主舞台和启动画面。

你也知道闪屏的好例子吗?

2 个答案:

答案 0 :(得分:3)

您熟悉JavaFX预加载器吗?对于至少您在该示例中所做的事情,它们可能是更好的方法:http://docs.oracle.com/javafx/2/deployment/preloaders.htm

关于任务完成时的“切换阶段”(我可能在这里忽略了这一点):为什么不在return语句之前添加以下内容:

Platform.runLater(new Runnable(){
    public void run() {
        initStage.close();
        showMainStage(foundFriends);
    }
}

可以说,直接以这种方式传递任务结果会更简单,将主视图的UI绑定到线程的value属性,不是吗?

答案 1 :(得分:1)

使用事件处理程序监视Task

的状态
friendTask.setOnSucceeded(new EventHandler() {

    @Override
    public void handle(Event t) {
        showMainStage(friendTask.valueProperty());
    }
});

详细信息如下:首先需要一些hideSplash()方法。然后,修改

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

部分为,

    showSplash(initStage, friendTask);
    friendTask.setOnSucceeded(new EventHandler() {

        @Override
        public void handle(Event t) {
            showMainStage(friendTask.valueProperty());
            hideSplash();
        }
    });
    new Thread(friendTask).start();

我希望现在很清楚。