How to initialize JavaFX controllers with the same model object?

后端 未结 3 765
予麋鹿
予麋鹿 2021-02-01 03:43

Scenario

I am creating a GUI where multiple views reference the same model object.

What I am Accustom to

In Swing, if

3条回答
  •  一向
    一向 (楼主)
    2021-02-01 04:39

    Update

    In addition to afterburner.fx, also checkout Gluon Ignite:

    Gluon Ignite allows developers to use popular dependency injection frameworks in their JavaFX applications, including inside their FXML controllers. Gluon Ignite creates a common abstraction over several popular dependency injection frameworks (currently Guice, Spring, and Dagger, but we plan at add more as the demand becomes obvious). With full support of JSR-330 Gluon Ignite makes using dependency injection in JavaFX applications trivial.

    Injection of model objects into controllers is also via @Inject, similar to afterburner.fx.

    Suggested Approach

    As you appear to be seeking a dependency injection framework, I think your best option is to use the afterburner.fx framework.

    afterburner.fx provides a way injecting model objects into your JavaFX controllers using the standard Java @Inject annotation.

    Alternative Dependency Injection Systems

    Spring is large and complicated and, unless you need a lot of its other functionality for your application, should not be considered due to its complexity.

    Guice is a lot simpler than Spring and a reasonable pick if you need a dependency injection framework with numerous features such as provider classes. But from the sound of it, you don't need all the features that Guice provides as you just want to a way to pass around singleton instances of objects in your application without explicitly looking them up.

    So, try out afterburner.fx and see if it fits your needs.

    afterburner.fx Sample Code

    Here is sample of injecting a model instance (the NotesStore) into a controller using afterburner.fx. The sample is directly copied from the afterburner.fx documentation.

    import com.airhacks.afterburner.views.FXMLView;
    
    public class NoteListView extends FXMLView {
        //usually nothing to do, FXML and CSS are automatically
        //loaded and instantiated
    }
    
    public class AirpadPresenter implements Initializable {    
        @Inject // injected by afterburner, zero configuration required
        NotesStore store;
    
        @FXML // injected by FXML
        AnchorPane noteList;
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            //view constructed from FXML
            NoteListView noteListView = new NoteListView();
    
            //fetching and integrating the view from FXML
            Parent view = noteListView.getView();
            this.noteList.getChildren().add(view);
        }
    }
    

    followme.fx is a basic sample application demonstrating how to use afterburner.fx. I did have a few issues getting followme.fx running straight out of the box due to Maven dependency incompatibilities, so I forked it's code and fixed some of the issues which prevented me from using it out of the box.

    Answers to addition questions from comments

    So from the NoteStore example, are you saying all I have to do is add the afterburner framework dependency and put @Inject on my model variable?

    No, you also need to create an associated class that extends FXMLView and instantiate that with a new call (similar to how NotesListView is created in the sample code above). If you are interested in continuing to investigate the afterburner.fx framework, then use the followme.fx project as basis because it provides complete source code for a very simple executable sample using the framework.

    I tried google guice and got it to work . . . you'll see in the constructor a game settings object is injected manually.

    I don't think you should have to use the Guice injector manually like that. I think you can set a controller factory on an FXMLLoader instance to initiate the injection. This is how the FXMLView in afterburner.fx does it. The exact detail of the injection mechanism used in Guice is going to differ from the afterburner.fx mechanism, but I think the broad concept of setting the controller factory remains similar.

    There is a demo of the set controller factory using FXML and Guice in the answer to: Associating FXML and Controller in Guice's Module configuration.

    It's a shame there is not a more straightforward way of doing this which does not cause you so many difficulties.

    As an inconsequential personal side note, I'm kind of ambivalent on the topic of dependency injection frameworks in general. Sure, they can help, but many times for simple things I'm often OK with a singleton with a getInstance method rather than the more sophisticated framework. Still I do see how in larger projects they can be useful and certainly they are very popular in certain Java frameworks.

提交回复
热议问题