首页 文章

如何使用相同的模型对象初始化JavaFX控制器?

提问于
浏览
23

Scenario

我正在创建一个GUI,其中多个视图引用相同的模型对象 .

What I am Accustom to

在Swing中,如果我希望所有视图都引用相同的模型,我会将模型传递给构造函数 .

What I am Currently Doing

在JavaFX中,我通过在每个视图/控制器加载后在视图/控制器(菜单栏,拆分窗格,制表符......)中使用setter方法来传递模型 . 我发现这非常俗气和麻烦 . 另外,我发现它不起作用,因为在某些情况下我需要在一些控制器小部件初始化之前已经存在于控制器中的模型 .

Lackluster Alternatives

(注意:我正在引用这些stackoverflow问题:

public CardOverviewTab() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("card_overview_tab.fxml"));
    fxmlLoader.setRoot(content);
    fxmlLoader.setController(this);

    try {
        fxmlLoader.load();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 并且SingleGameSetup控制器将卡概述选项卡自动注入变量:
public class SingleGameSetupController extends AnchorPane {

    @FXML private CardOverviewTab cardOverviewTab;

    // Rest of the class
}
  • 包含卡片概述选项卡的fxml部分如下所示:
<CardOverviewTab fx:id="cardOverviewTab" />
  • 这样我不需要担心手动加载控制器,但我仍然有设置模型的问题 .

  • 在FXMLLoader上设置控制器

  • 此选项与我习惯的类似,将模型作为参数传递给构造函数,但它仍然存在使用FXMLLoader手动加载控制器的问题 .

  • 活动 Bus

  • 我没有读太多内容,但从我所看到的事件总线似乎是不活跃和过时的 .

  • 辛格尔顿

  • 这类似于对控制器可以检索的模型对象的公共静态引用,但我再次寻找更好的解决方案 . 另外,我不想要单身模型 .

What I am Looking for

有没有办法以不那么繁琐的方式传递模型对象?我正在寻找一种简单的方法,如将模型传递给构造函数,但我不想处理通过FXMLLoader手动加载控制器,或者在加载控制器后设置模型 . 也许有一个类来检索模型是最好的选择,但我要求以防万一有更好的方法 .

3 回答

  • 15

    我一直在研究这个问题,我发现依赖注入和单例(对于模型)是我的最佳设计 . 我了解到,在每个控制器中使用模型的setter方法是依赖注入的一种形式,就像通过构造函数传递模型一样 . Spring和Guice是帮助它的框架 .

    我尝试使用Spring,如下所示:http://www.zenjava.com/2011/10/23/better-controller-injection/但是当配置类试图加载控制器时遇到了问题,它无法加载成员控制器 . 这可能不是一个Spring问题,但我认为我并不在乎花时间让它工作 . 另外,我将不得不浏览所有控制器文件并编辑它们的创建方式 .

    我四处搜索并做了很多阅读,发现这篇文章最能表达我想要做的事情:https://forums.oracle.com/thread/2301217?tstart=0 . 由于本文引用了建议的改进,因此JavaFX中尚不存在这些改进 . 但是当他们这样做时,我将实施它们 . 举个例子,能够通过fxml注入模型:

    <usevar name="model" type="com.mycom.myapp.ModelObject"/>
    
  • 0

    Update

    除了afterburner.fx之外,还要结帐Gluon Ignite

    Gluon Ignite允许开发人员在他们的JavaFX应用程序中使用流行的依赖注入框架,包括在他们的FXML控制器中 . Gluon Ignite在几个流行的依赖注入框架(目前是Guice,Spring和Dagger)上创建了一个共同的抽象,但我们计划在需求变得明显时增加更多 . 在JSR-330的完全支持下,Gluon Ignite使JavaFX应用程序中的依赖注入变得微不足道 .

    将模型对象注入控制器也是通过@Inject,类似于afterburner.fx .

    Suggested Approach

    当您正在寻求依赖注入框架时,我认为您最好的选择是使用afterburner.fx framework .

    afterburner.fx提供了一种使用标准Java @Inject注释将模型对象注入JavaFX控制器的方法 .

    Alternative Dependency Injection Systems

    Spring虽然庞大而复杂,除非你需要很多其他功能应用程序,由于其复杂性,不应该考虑 .

    如果你需要一个具有许多功能的依赖注入框架,例如提供者类,Guice比Spring简单得多,也是一个合理的选择 . 但是从它的声音来看,你不需要Guice提供的所有功能,因为你只想在应用程序中传递对象的单例实例,而无需明确查找它们 .

    因此,尝试使用afterburner.fx并查看它是否符合您的需求 .

    afterburner.fx Sample Code

    以下是使用afterburner.fx将模型实例( NotesStore )注入控制器的示例 . 样本直接从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是一个基本的示例应用程序,演示了如何使用afterburner.fx . 由于Maven依赖不兼容性,我确实有一些问题让followme.fx直接开箱即用,所以我修复了一些阻止我开箱即用的问题 .

    Answers to addition questions from comments

    那么从NoteStore示例中,您是否说我要做的就是添加afterburner框架依赖项并将@Inject放在我的模型变量上?

    不,您还需要创建一个扩展FXMLView的关联类,并使用新调用实例化它(类似于上面示例代码中创建NotesListView的方式) . 如果您有兴趣继续研究afterburner.fx框架,那么请使用followme.fx项目作为基础,因为它为使用框架的非常简单的可执行样本提供了完整的源代码 .

    我尝试了谷歌guice并让它工作 . . . 您将在构造函数中看到手动注入游戏设置对象 .

    我不认为你应该像这样手动使用Guice注射器 . 我想你可以在FXMLLoader实例上set a controller factory来启动注入 . 这就是afterburner.fx中FXMLView的作用 . Guice中使用的注入机制的确切细节将与afterburner.fx机制不同,但我认为设置控制器工厂的广泛概念仍然相似 .

    在答案中有一个使用FXML和Guice的设置控制器工厂的演示:Associating FXML and Controller in Guice's Module configuration .

    遗憾的是,没有更简单的方法可以做到这一点,这不会给你带来太多困难 .

    作为一个无关紧要的个人注释,我总体上对依赖注入框架的主题感到矛盾 . 当然,他们可以提供帮助,但很多时候对于简单的事情,我通常可以使用带有getInstance方法的单例而不是更复杂的框架 . 我仍然看到在大型项目中它们如何有用,当然它们在某些Java框架中非常流行 .

  • 0

    DataFX Framework有一个名为DataFX-Flow的新API . 使用此API,您只需在视图控制器中注入对象即可 . 这里支持其他的Afterburner.fx范围 . 你可以在这里找到一个例子:http://www.guigarage.com/2013/12/datafx-controller-framework-preview/

相关问题