0

I have a JavaFX Application. I have a button that when clicked calls an action and loads another fxml file. This works perfectly.

I decided to place this functionality from within the menu of the application.

So, I created a Menu and I added Menu Items from within the Scene builder. I properly assign the 'On Action' event, the same way I did with my other button. However I get the following error when I click:

Glass detected outstanding Java exception at -[GlassViewDelegate sendJavaMouseEvent:]:src/com/sun/mat/ui/GlassViewDelegate.m:541
Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException

Caused by: java.lang.ClassCastException: javafx.scene.control.MenuItem cannot be cast to javafx.scene.Node
at plataformavalidezpredictiva.MainController.handleAction(MainController.java:60)
... 38 more

This is the code for the handler. Once again, this works for a button I placed within the UI and doesn't work from the menu bar:

public void handleAction(ActionEvent event) throws Exception{
    Node node = (Node)event.getSource();
    Stage stage=(Stage) node.getScene().getWindow();

    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("fxml/GUIFile.fxml"));        

    Parent root = (Parent)fxmlLoader.load();          
    Scene scene = new Scene(root); 
    stage.setScene(scene);

    stage.show();
}    

The line that seems to give me the problem is:

Node node = (Node)event.getSource();

Any ideas?

Edit: I saw the post here Unable to get Scene from MenuItem in JavaFX but that didn't work for me, because it didn't find the getScene() method for the menu bar.

Community
  • 1
  • 1
Dynelight
  • 2,072
  • 4
  • 25
  • 50
  • As it says in the error message, a MenuItem isn't a Node, so your cast fails. Can you explain what you meant by "not finding getScene() method for the MenuBar"? Did you try injecting the menu bar into your controller and calling getScene() on it? – James_D Apr 05 '14 at 23:23
  • The method doesn't exists. I didn't try doing that, do I just need to declare it? – Dynelight Apr 05 '14 at 23:44
  • I don't know what you mean by that. [MenuBar is a subclass of Node](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/MenuBar.html) and [Node has a getScene() method](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#getScene--). So the method exists. I posted a complete example. – James_D Apr 06 '14 at 00:53

1 Answers1

3

Inject some node (e.g. the MenuBar, but it really can be any node in the same scene) into the controller. Call getScene() on that node and getWindow() on the Scene.

E.g.

Main.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuItem?>

<BorderPane xmlns:fx="http://javafx.com/fxml" fx:controller="exitfrommenu.MainController">
    <top>
    <MenuBar fx:id="menuBar">
    <Menu text="File">
    <MenuItem  text="Exit" onAction="#exit"/>
    </Menu>
    </MenuBar>
    </top>
</BorderPane>

MainController.java

package exitfrommenu;

import javafx.fxml.FXML;
import javafx.scene.control.MenuBar;

public class MainController {
    @FXML
    private MenuBar menuBar ;

    @FXML
    private void exit() {
            Stage stage = (Stage) menuBar.getScene().getWindow() ;
            // This exits the application, but of course you can do anything
            // you like with the stage, such as showing a new scene in it:
        stage.hide();
    }
}

Main.java

package exitfrommenu;

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("Main.fxml"));
            Scene scene = new Scene(root,400,400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322