如何在控制器类中引用舞台?

6

Main.class

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("/application/Main.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

MainController.class

    public class MainController implements Initializable {

    @FXML private MediaView mv;
    private MediaPlayer mp;
    private Media me;

    @FXML Slider volumeSlider;

    DoubleProperty width;
    DoubleProperty height;

    Stage stage;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // TODO Auto-generated method stub
        String path = new File("src/media/my.mp4").getAbsolutePath();
        me = new Media(new File(path).toURI().toString());
        mp = new MediaPlayer(me);
        mv.setMediaPlayer(mp);
        //mp.setAutoPlay(true);

        stage = (Stage) mv.getScene().getWindow();  // Error occured

        width = mv.fitWidthProperty();
        height = mv.fitHeightProperty();
        width.bind(Bindings.selectDouble(mv.sceneProperty(), "width"));
        height.bind(Bindings.selectDouble(mv.sceneProperty(), "height"));

        volumeSlider.setValue(mp.getVolume() * 100);
        volumeSlider.valueProperty().addListener(new InvalidationListener() {

            @Override
            public void invalidated(Observable observable) {
                // TODO Auto-generated method stub
                mp.setVolume(volumeSlider.getValue() / 100);
            }
        });
    }

    public void play(ActionEvent event){
        mp.play();
        mp.setRate(1);
    }
    public void pause(ActionEvent event){
        mp.pause();
    }
    public void fast(ActionEvent event){
        mp.setRate(2);
    }
    public void slow(ActionEvent event){
        mp.setRate(.5);
    }
    public void reload(ActionEvent event){
        mp.seek(mp.getStartTime());
        mp.play();
    }
    public void start(ActionEvent event){
        mp.seek(mp.getStartTime());
        mp.stop();
    }
    public void last(ActionEvent event){
        mp.seek(mp.getTotalDuration());
        mp.stop();
    }
    public void fullScreen(ActionEvent event){

    }
}

Error

javafx.fxml.LoadException: 
/C:/Users/SOONMYUN/workspace/MediaPlayer/bin/application/Main.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
    at application.Main.start(Main.java:17)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
    at application.MainController.initialize(MainController.java:44)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    ... 17 more

我希望能够在控制器类中获取来自主类的舞台,但是失败了。

原因是我应该在控制器类中使用setFullScreen函数。

2个回答

15

我正在回答如何将舞台对象从主类传递到您的控制器类中,需要在控制器类中创建一个函数。

public void setStage(Stage stage){
this.stage=stage;
}

现在在您的主类中调用此函数,如下所示:

 FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/application/Main.fxml"));
                Parent root = (Parent) fxmlLoader.load();
  ((MainController) fxmlLoader.getController()).setStage(primaryStage);

如果您想在不将舞台对象从主类传递到类控制器的情况下获取舞台对象,可以按照以下方式操作:

1. 给 AnchorPane 分配 ID,例如 fx:id="ap",然后在您的控制器类中:

@FXML
AnchorPane ap;

2.您想要放置物体的位置

Stage stage = (Stage) ap.getScene.getWindow();

非常感谢!它正在运行。 - Soonmyun Jang
很高兴能够帮到您。请点赞并接受答案。 - Sahil Manchanda
你好。setStage函数成功运行,但是当我尝试在我的控制器类中使用stage时,stage.sizeToScene()会抛出nullpointerexception异常。我在同一控制器类中的另一个函数authenticate(ActionEvent event)中使用了stage.sizeToScene()。我需要将stage传递到这个authenticate(ActionEvent event)函数中吗?谢谢。 - Riley Fitzpatrick
@RileyFitzpatrick NullPointerException 表示在你尝试使用它时它没有被初始化。确保你已经像答案中所述调用了 setStage。如果仍然出现异常,你可以使用任何 UI 元素(如按钮)来访问 stage 对象,就像答案中指定的其他方式一样。如果需要帮助,请告诉我。 - Sahil Manchanda
7天的搜索终于在控制器中得到了一个阶段。但是为什么我们不能将它声明为FXMLDocumentController文件中的私有全局变量?作为局部变量,它可以正常工作。 - Shiva_Adasule
显示剩余3条评论

2

从控制器访问 stage:

  • Create a setter method for stage variable in your Controller class
  • Get instance of the controller in your Main.java class

  • Set the stage variable of controller through setter method in Main.java

    Illustration:

    Step 1 :

        public class MainCOntroller {
    
         private Stage primaryStage;
    
            public void setPrimaryStage(Stage primaryStage){
                       this.primaryStage = primaryStage;
             }
                .....
               .....      
         }       
    

    Step 2 and 3: get the instance of controller and set the stage using setter method

      public class Main extends Application {
      @Override
      public void start(Stage primaryStage) {
        try {
          FXMLLoader loader = new FXMLLoader(getClass().getResource("/application/Main.fxml"));
         Parent root = (Parent)loader.load();
    
         MainController controller = (MainController) loader.getController(); 
    
          //set stage 
           controller.setPrimaryStage(primaryStage);
      } catch(Exception e) {
            e.printStackTrace();
        }
    }
    

我很感激你。由于你的答案,我解决了问题! - Soonmyun Jang
欢迎。 - MR.JOIS

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