Associer FXML et Controller dans la configuration du Module de Guice

dans mon Module Guice je veux associer des fichiers FXML et leurs contrôleurs, il ressemble actuellement à ceci:

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**

cependant dans la méthode loadController(String url) j'ai des problèmes avec cette ligne:

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

Comment puis-je accéder à la méthode getInstance de Guice à partir d'un Module Guice? Est que ou quelque chose d'équivalent possible?

5
demandé sur stefan.at.wpf 2013-04-13 21:33:21

2 réponses

je suis l'auteur de fx-guice , une bibliothèque open-source qui peut être utilisée pour utiliser Guice dans vos applications JavaFX. La Bibliothèque est sous licence avec la licence Apache v2 et peut être obtenue via le dépôt central Maven .

même si elle pourrait pas répondre à votre question exacte, je vous suggère de jeter un oeil à mon projet, qui est livré avec pas mal d'exemples:

Accueil du projet: → http://github.com/cathive/fx-guice/

L'idée principale de mon cadre est: Au lieu d'étendre "javafx.application.L'Application" étendre "com.cathive.fx.GuiceApplication". Vous pouvez alors tout simplement @injecter les instaces de "GuiceFXMLLoader" où vous voulez et utiliser ces instances spéciales de FXMLLoader pour charger vos définitions D'UI. Dans vos classes FXML-controller, vous pouvez mélanger les irritations @Inject et @FXML comme vous le souhaitez.

http://bit.ly/139fKQV

mon framework offre également un tas de fonctionnalités concernant les composants JavaFX "Guicifiés", qui lient une classe Java et un seul fichier FXML (en utilisant une annotation spéciale: "@FXMLComponent"). J'ai écrit un petit exemple de "calculatrice" dont les sources peuvent être obtenues à partir des pages Github (voir ci-dessus). Les parties pertinentes du code peuvent être trouvées ici:

CalculatorAppPane.java: → http://bit.ly/10YMVoM

CalculatorAppPane.FXML: → http://bit.ly/13loYv8

Espère que ça aide. :- )

3
répondu headcr4sh 2013-06-05 16:04:40

je vais suggérer l'une des nombreuses approches pour associer un contrôleur à un fichier FXML , je suppose que vous utilisez le FX:controller étiquette dans votre fichier FXML .

pour la démonstration, je vais implémenter une application de démonstration hébergée sur github avec un bouton au milieu de l'étape.

enter image description here

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

View.FXML

notez que nous nous référons à l'interface dans le fichier FX:controller dans le fichier FXML , et non à l'implémentation, de sorte que nous pouvons réutiliser la vue fxml avec d'autres controllers implémentant l'interface.

<?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>

IController

une interface que le contrôleur doit mettre en œuvre , le printButton() pour imprimer un message à l'écran , et getRoot() pour obtenir la vue de panneau.

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

public interface IController extends Initializable {

    public void printButton();  

    public Parent getRoot();
}

contrôleur

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 !!");
    }
}

InjectingFXMLLoader

une classe avec une méthode statique qui obtiennent une mise en œuvre concrète d'un contrôleur et URL du fichier FXML et renvoie le contrôleur de la vue.

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();
    }
}

AppModule

dans le module guice , nous utilisons la classe InjectingFXMLLoader pour associer une implémentation concrète du contrôleur avec le fichier correspondant FXML . l'utilisation de la méthode @fournit la méthode .

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"));
    }
}

App

la classe principale qui montrent la vue

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();
    }
}
1
répondu tarrsalah 2013-04-14 02:14:10