Model view controller – JavaFX includes fxml in fxml without controller

I am writing an application using JavaFX

My scenario is defined in different fxml files

Because I tried to use MVC mode, I didn't set the controller in the fxml file. I used setcontroller on fxmlloader

Everything works normally, but I have Onmen's MainMenu and all its functions in a separate controller and a separate fxml file

I tried

<fx:include source="Menubar.fxml"/>

And create a controller for the fxml file. When I set the controller in the fxml file, I can't compile the source code How do I set up a controller for an included fxml file?

startpage. Fxml gets its controller "startpage"

FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/startpage.fxml"));
        loader.setController(new Startpage(m));
        Pane mainPane = loader.load();

startpage. Fxml contains menubar Fxml, now how to set the controller of the menu bar control? Or how to easily include menubarcontroller in every other controller?

Solution

I think you need to use controllerfactory in the loader to achieve what you want When you use controllerfactory, you specify the class name of the controller in the fxml file, but the controller factory allows you to control how to map to the object (so you can still build it, pass it in the model, etc.) When specifying controllerfactory for fxmlloader, the factory is also used to create controllers for any < FX: include > in the fxml file

Finally, please note that you can inject the controller of the included fxml file into the "main" fxml file, as described in the "nested controllers" section of the fxml documentation

So if startpage Fxml looks like this:

<!-- imports etc -->
<BorderPane fx:controller="com.example.Startpage" ... >
  <top>
    <fx:include source="Menubar.fxml" fx:id="menubar" />
  </top>
  <!-- etc ... -->
</BorderPane>

And menubar Fxml looks like

<!-- imports etc -->
<MenuBar fx:controller="com.example.MenubarController" ... >
  <!-- etc... -->
</MenuBar>

You can then control the instantiation of the controller class using the following command:

FXMLLoader loader = new FXMLLoader(getClass().getResource("../fxml/startpage.fxml"));

Model m = ... ;

Startpage startpageController = new Startpage(m);
MenubarController menubarController = new MenubarController(m);

Callback<Class<?>,Object> controllerFactory = type -> {
    if (type == Startpage.class) {
        return startpageController ;
    } else if (type == MenubarController.class) {
        return menubarController ;
    } else { 
        // default behavior for controllerFactory:
        try {
            return type.newInstance();
        } catch (Exception exc) {
            exc.printStackTrace();
            throw new RuntimeException(exc); // fatal,just bail...
        }
    }
};

loader.setControllerFactory(controllerFactory);

Pane mainPane = loader.load();

Now, if necessary, you've actually referenced two controllers in your application code, but you can do the same

public class Startpage {

    public final Model m ;

    // note the name of this field must be xController,// where x is the fx:id set on the <fx:include>:

    @FXML
    private final MenubarController menubarController ;

    public Startpage(Model m) {
        this.m = m ;
    }

    // ...
}

Therefore, the main controller now has a reference to the menu bar controller

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>