JavaFX如何更改舞台(stage)?

14

我正在使用Netbeans 7.2和Scene Builder 1.0来开发JavaFX应用程序。 我已经设置好了主屏幕,并希望点击一个按钮后它会关闭主窗口并打开另一个窗口。 主Stage对象位于主类中,但控制器类是单独的,无法访问它,因为它不是静态的且位于不同的类中。 如何更改场景或舞台?

4个回答

35

下载JavaFX示例,查找FXML-LoginDemo项目,这就是你需要的。为了方便参考,我在这里复制粘贴了主要的Java类;)

/*
 * Copyright (c) 2008, 2011 Oracle and/or its affiliates.
 * All rights reserved. Use is subject to license terms.
 *
 * This file is available and licensed under the following license:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the distribution.
 *  - Neither the name of Oracle Corporation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package demo;

import demo.model.User;
import demo.security.Authenticator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

/**
 * Main Application. This class handles navigation and user session.
 */
public class App extends Application {
    private Stage stage;
    private User loggedUser;

    private static App instance;

    public App() {
        instance = this;
    }

    public static App getInstance() {
        return instance;
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    @Override public void start(Stage primaryStage) {
        try {
            stage = primaryStage;
            gotoLogin();
            primaryStage.show();
        } catch (Exception ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public User getLoggedUser() {
        return loggedUser;
    }

    public boolean userLogging(String userId, String password){
        if (Authenticator.validate(userId, password)) {
            loggedUser = User.of(userId);
            gotoProfile();
            return true;
        } else {
            return false;
        }
    }

    public void userLogout(){
        loggedUser = null;
        gotoLogin();
    }

    private void gotoProfile() {
        try {
            replaceSceneContent("profile.fxml");
        } catch (Exception ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void gotoLogin() {
        try {
            replaceSceneContent("login.fxml");
        } catch (Exception ex) {
            Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private Parent replaceSceneContent(String fxml) throws Exception {
        Parent page = (Parent) FXMLLoader.load(App.class.getResource(fxml), null, new JavaFXBuilderFactory());
        Scene scene = stage.getScene();
        if (scene == null) {
            scene = new Scene(page, 700, 450);
            scene.getStylesheets().add(App.class.getResource("demo.css").toExternalForm());
            stage.setScene(scene);
        } else {
            stage.getScene().setRoot(page);
        }
        stage.sizeToScene();
        return page;
    }
}

2
现在这样做是正确的吗?我的意思是,我可以在App类之外调用.replaceSceneContent吗?或者说在今天(2015年)有更好的方法来切换场景吗?谢谢=) - user2582318
我该如何在控制器类中使用这个?还是说我只能在主应用程序中使用它? - Ahmed Hasn.
这个答案已经过时了,今天不再适用 :( - Dan A.S.

6

我可能会说类似的话,但这是我的做法:

(在这个例子中,我从Login.fxml过渡到Home.fxml)。

在LoginController.fxml类内,我创建了以下方法:

@FXML
private void login(javafx.event.ActionEvent event) throws IOException
{
    if(pwf1.getText().equals("dolphin"))
    {
            Parent blah = FXMLLoader.load(getClass().getResource("Home.fxml"));
            Scene scene = new Scene(blah);
            Stage appStage = (Stage) ((Node) event.getSource()).getScene().getWindow();
            appStage.setScene(scene);
            appStage.show();
    }
    else
    {
            label1.setText("Password is incorrect. Please Try Again");
    }
}

就是这样了。;)


2

你也可以这样做:

按照以下方式修改你的controller.java文件

Stage thisStage;

public void setStage (Stage stage){
    thisStage = stage;
}

public void showStage(){
    thisStage.setTitle("Titel in der MainController.java geändert");
    thisStage.show();
}

重要的是,在initialize方法中不要使用thisStage。

按照以下方式修改您的Mainclass:

@Override
public void start(Stage stage) throws Exception {
    URL location = getClass().getResource("Main.fxml");
    FXMLLoader fxmlLoader = new FXMLLoader();
    fxmlLoader.setLocation(location);
    fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());
    Parent root = (Parent) fxmlLoader.load(location.openStream());
    Scene scene = new Scene(root);
    stage.setScene(scene);
    MainController mainController = fxmlLoader.getController();
    mainController.setStage(stage);
    mainController.showStage();
}

您可以在此处下载一个示例项目(NetBeans)这里


链接已经失效了,你能给我们提供另一个链接吗? - Ahmed Hasn.

2
根据您的问题,最近我正在开发一个iOS等效的NavigationController用于JavaFX,使用最简单的推送和关闭视图的思路。
让我与社区分享代码:https://github.com/jalopezsuarez/javafx-screens 这个想法是为您提供一个非常简单的环境,以帮助您在屏幕之间切换。
希望能对您有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接