1

I have a fxml file build from fxml builder and I am using it by a loader in Java.

URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml"); FXMLLoader loader = new FXMLLoader(resource, resourceBundle); Pane rootPane = (Pane) loader.load(); 

this fxml file maps click event to my class;

<Group id="Group" layoutX="0.0" layoutY="0.0" onMouseReleased="#handleThis" scaleX="1.0" scaleY="1.0"> ... <Group/> 

so I implement my handler in my class, lets call it MyClass;

public class MyClass { public void createScene() throws IOException { URL resource = getClass().getClassLoader().getResource("fxmlFile.fxml"); FXMLLoader loader = new FXMLLoader(resource, resourceBundle); Pane rootPane = (Pane) loader.load(); ... } @FXML public void handleThis(ActionEvent event) { System.out.println("from MyClass"); } ... } 

Now I extend MyClass as MyExtendedClass and override handleThis method;

public class MyExtendedClass extends MyClass { @Override public void handleThis(ActionEvent event) { System.out.println("from MyExtendedClass"); } } 

My question is, I cannot manage to work handle method in my extended class. It does not overrides it. How can I achieve to make it print "from MyExtendedClass" instead of "from MyClass"?

6
  • What are you declaring as the controller in the FXML file? Commented May 13, 2015 at 11:22
  • have you tried onMouseRelease="#MyExtendedClass.handleThis" ? Commented May 13, 2015 at 11:24
  • I set controller as MyClass and I should not change it Commented May 13, 2015 at 11:35
  • Then how would the FXMLLoader even know about the subclass? Commented May 13, 2015 at 12:17
  • FXMLLoader is called in MyClass Commented May 13, 2015 at 12:25

1 Answer 1

1

When createScene() is called on an instance of MyExtendedClass, the FXMLLoader parses the FXML file, reads the fx:controller="MyClass" attribute and instantiates a new object of type MyClass. That is why the base method is always called. The FXMLLoader doesn't know about MyExtendedClass.

There is a - hackish - way to achieve what you want (i.e. doing the loading in MyClass and still defining the controller in FXML):

public class MyClass { public void createScene() { try { FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("FXML.fxml")); // set a controller factory that returns this instance as controller // (works in this case, but not recommended) loader.setControllerFactory(controllerType -> this); pane = (Pane) loader.load(); } catch (IOException e) { throw new RuntimeException(e); } } } 

It would be cleaner to instantiate the controller and pass it to the FXMLLoader.
For this the fx:controller="" attribute must be removed from the FXML file.

public class Main extends Application { @Override public void start(Stage primaryStage) throws Exception { MyClass controller = new MyExtendedClass(); FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("FXML.fxml")); loader.setController(controller); Pane pane = (Pane) loader.load(); primaryStage.setScene(new Scene(pane)); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 

Or use fx:controller="MyClass" to define the base type in the FXML file and let a controller factory decide the actual implementation.

public class Main extends Application { @Override public void start(Stage primaryStage) throws Exception { FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("FXML.fxml")); loader.setControllerFactory(controllerType -> { if (MyClass.class.equals(controllerType)) return new MyExtendedClass(); else return null; // return some other controller }); Pane pane = (Pane) loader.load(); MyClass controller = (MyClass) loader.getController(); primaryStage.setScene(new Scene(pane)); primaryStage.show(); } public static void main(String[] args) { launch(args); } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.