6

在我的 Guice 模块中,我想关联 FXML 文件和它们的控制器,目前它看起来像这样:

public class GuiceModule extends AbstractModule 
{   
    @Override
    protected void configure()
    {
        // associate controllers and fxml files
        bind(MainController.class).toInstance((MainController)loadController("/main.fxml"));
        bind(SubController.class).toInstance((SubController)loadController("/content.fxml"));
    }

    protected Object loadController(String url)
    {
        InputStream fxmlStream = null;
        try
        {
            fxmlStream = getClass().getResourceAsStream(url);
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(getClass().getResource(url));


            loader.setControllerFactory(new Callback<Class<?>, Object>() {

                public Object call(Class<?> clazz) { // clazz because class is a reserved word
                    return injector.getInstance(clazz); // PROBLEM: no access to the injector here
                }
            });

            loader.load(fxmlStream);
            return loader.getController();
        }

        // [..] exception handling

    }
}**strong text**

但是在该loadController(String url)方法中,我遇到了该行的问题:

return injector.getInstance(clazz); // PROBLEM: no access to the injector here

如何getInstance从 Guice 模块中访问 Guice 的方法?那是可能的吗?

4

2 回答 2

3

我是fx-guice的作者,这是一个可用于在 JavaFX 应用程序中使用 Guice 的开源库。该库使用 Apache License v2 获得许可,可以通过中央Maven 存储库获得。

尽管它可能无法回答您的确切问题,但我建议您查看我的项目,该项目捆绑了很多示例:
项目主页:→  http://github.com/cathive/fx-guice/

我的框架的主要思想是:不是扩展“javafx.application.Application”,而是扩展“com.cathive.fx.GuiceApplication”。然后,您可以在任何需要的地方简单地 @Inject "GuiceFXMLLoader" 实例,并可以使用这些特殊的 FXMLLoader 实例来加载您的 UI 定义。在您的 FXML 控制器类中,您可以根据需要混合使用 @Inject 和 @FXML 注释。
→  http://bit.ly/139fKQV

我的框架还提供了一系列有关“Guicified”JavaFX 组件的功能,这些组件将 Java 类和单个 FXML 文件绑定在一起(使用特殊注释:“@FXMLComponent”)。我写了一个简短的“计算器”示例,其来源可以从 Github 页面获得(见上文)。代码的相关部分可以在这里找到:
CalculatorAppPane.java: →  http://bit.ly/10YMVoM
CalculatorAppPane.fxml: →  http://bit.ly/13loYv8

希望有帮助。:-)

于 2013-06-05T16:04:40.600 回答
1

我将建议将控制器与FXML文件相关联的多种方法之一,我会假设您在FXML文件中使用fx:controller标记。

出于演示目的,我将实现一个托管在github上的演示应用程序,在舞台中间有一个按钮。

在此处输入图像描述

Demo__
     |___ App.java
     |___ AppModule.java
     |___ IController.java
     |___ Controller.java
     |___ InjectingFXMLLoader.java
     |___ fxml
              |__view.fxml

查看.fxml

请注意,我们在FXML文件中引用fx:controller中的接口,而不是实现,因此我们可以将 fxml 视图与其他实现该接口的控制器一起使用。

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

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.paint.*?>

<BorderPane fx:id="root" xmlns:fx="http://javafx.com/fxml" fx:controller="org.tarrsalah.stackoverflow.guice.fx.IController" >
    <center>
        <HBox alignment="CENTER" prefHeight="-1.0" prefWidth="-1.0">
            <children>
                <Button fx:id="fx_print" alignment="CENTER" contentDisplay="CENTER" defaultButton="true" mnemonicParsing="false" onAction="#printButton" text="Print !" HBox.hgrow="ALWAYS" />
            </children>
            <BorderPane.margin>
                <Insets bottom="20.0" top="10.0" />
            </BorderPane.margin>
        </HBox>
    </center>
</BorderPane>

控制器

控制器必须实现的接口,将printButton()消息打印到屏幕,并getRoot()获取面板视图。

import javafx.fxml.Initializable;
import javafx.scene.Parent;

public interface IController extends Initializable {

    public void printButton();  

    public Parent getRoot();
}

控制器

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.scene.Parent;

public class Controller implements IController {

    @FXML
    Parent root;

    public void initialize(URL url, ResourceBundle rb) {
    }

    public Parent getRoot() {
        return root;
    }

    public void printButton() {
        System.out.println("Hello Guice !!");
    }
}

注入FXMLLoader

具有一个静态方法的类,该方法获取控制器的具体实现FXML 文件的URL,并返回视图的控制器。

import java.io.IOException;
import java.net.URL;
import javafx.fxml.FXMLLoader;
import javafx.util.Callback;

public class InjectingFXMLLoader {
    /**
     * 
     * @param <N>
     * @param injector
     * @return a controller injected within an FXML.
     */
    public static <N> N loadFXMLController(final N controller, URL url) throws IOException {
        FXMLLoader loader= new FXMLLoader();
        loader.setLocation(url);
        loader.setControllerFactory(new Callback<Class<?>, Object>() {

            public Object call(Class<?> p) {
                return controller;
            }
        });
        loader.load();
        return loader.getController();
    }
}

应用模块

在 guice 模块中,我们使用 InjectingFXMLLoader 类将控制器的具体实现与相应的FXML文件相关联。使用@Provides方法。

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import java.io.IOException;

public class AppModule extends AbstractModule {

    @Override
    protected void configure() {
    }

    /**
     *
     * @return IController
     * @throws IOException
     */
    @Provides
    public IController getIController() throws IOException {
        return InjectingFXMLLoader.loadFXMLController(new Controller(), getClass().getClassLoader().getResource("fxml/view.fxml"));
    }
}

应用程序

显示视图的主类

import com.google.inject.Guice;
import javafx.application.Application;
import javafx.scene.SceneBuilder;
import javafx.stage.Stage;

public class App extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setScene(SceneBuilder
                .create()
                .root(Guice.createInjector(new AppModule()).getInstance(IController.class).getRoot())
                .height(160)
                .width(200)
                .build());
        stage.show();
    }
}
于 2013-04-14T02:07:46.757 回答