2017-12-01 5 views
0

JavaFXとCDIを統合したいと思います。いくつかの良い例が、これらのもののようなことについてウェブ上でありますJavaFXとCDI:多くのステージを注入する方法

https://dzone.com/articles/fxml-javafx-powered-cdi-jboss http://fxapps.blogspot.com.br/2017/10/using-cdi-20-in-javafx-application.html

しかし、彼らはより多くを注入することができないので、私が見てきたすべての例は、現実の世界では動作しません。 1つのステージ(primaryStage)がある場合、私はどのようにわかりません。

だから私は(...例えばモーダルウィンドウで使用するために)、それは複数のステージを注入するのJavaFX/CDIプロジェクトで可能ですかどうかを知りたい

感謝です!

+1

ステージに何かを挿入するのは不思議です。あなたが提供したリンクのどちらもDIフレームワークを使用してステージを管理しません。どのコンポーネントがステージに依存するかはわかりません。通常は、JavaFXで依存関係注入フレームワークを使用してモデルとサービスをコントローラに注入し、モデルやサービス間に他の依存関係を確立します。 –

+0

James_D、返信いただきありがとうございます!問題は、モーダルダイアログを表示するために私はそれらのために新しいステージが必要なため、問題はどうすればそのステージを得ることができるかということです。 **新しいStage()**を呼び出すと、CDI Beanはそのステージのコントローラに注入されません。 –

+0

新しいステージを作成するだけです。なぜそれを作成するためにDIフレームワークが必要ですか? –

答えて

3

ステージを管理するためにCDIを使用する必要はありません。ステージ自体はSceneです。彼らはあなたが管理する必要がある他のオブジェクトに依存することはありません。 FXMLLoaderにDIフレームワークからコントローラインスタンスを取得するcontrollerFactoryがあることを確認するだけです。

ここでは簡単な例を示します(注意:以前はCDI/Weldを使ったことがないので、ここでは最適な方法はないかもしれません)。

まず、それが適切なコントローラを取得し、コントローラの工場を公開するために、おそらく良い考えです:

package app; 

import javax.enterprise.context.ApplicationScoped; 
import javax.enterprise.inject.Instance; 
import javax.inject.Inject; 

import javafx.util.Callback; 

@ApplicationScoped 
public class CDIControllerFactory implements Callback<Class<?>, Object> { 

    @Inject 
    private Instance<Object> instance ; 

    @Override 
    public Object call(Class<?> type) { 
     Object controller = instance.select(type).get(); 
     return controller; 
    } 

} 

ここでは、すべてのコントローラと共有したいモデルクラスです。

package app; 

import javax.enterprise.context.ApplicationScoped; 

import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 

@ApplicationScoped 
public class Model { 

    private final ObservableList<String> names = FXCollections.observableArrayList(); 

    public ObservableList<String> getNames() { 
     return names ; 
    } 

    public void addName(String name) { 
     names.add(name); 
    } 
} 

テスト・アプリケーションだけで(名前のリストを持つ)リストビューとダイアログから、新しい名前を追加するためのボタンがあります:我々は唯一のインスタンスをしたいので、我々はそれ@ApplicationScopedします。メインコントローラは

package app; 

import java.io.IOException; 

import javax.inject.Inject; 

import javafx.fxml.FXML; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Scene; 
import javafx.scene.control.ListView; 
import javafx.stage.Modality; 
import javafx.stage.Stage; 

public class MainController { 

    @Inject 
    private Model model ; 
    @Inject 
    private CDIControllerFactory controllerFactory ; 

    @FXML 
    private ListView<String> listView ; 

    @FXML 
    private void initialize() { 
     listView.setItems(model.getNames()); 
    } 

    @FXML 
    private void showAddDialog() throws IOException { 
     FXMLLoader loader = new FXMLLoader(AddNameController.class.getResource("AddNameDialog.fxml")); 
     loader.setControllerFactory(controllerFactory); 
     Scene scene = new Scene(loader.load()); 
     Stage stage = new Stage(); 
     stage.initModality(Modality.APPLICATION_MODAL); 
     stage.setScene(scene); 
     stage.show(); 
    } 
} 

FXMLLoaderのコントローラファクトリを使用しています。ステージは「手で」作成することができます。

新しい名前を追加するためのダイアログのコントローラです。それはCDIを経由して、同じモデルのインスタンスへの参照を持っているかに注意してください:

ここ
package app; 

import javax.enterprise.inject.Default; 
import javax.inject.Inject; 

import javafx.fxml.FXML; 
import javafx.scene.control.TextField; 

@Default 
public class AddNameController { 

    @Inject 
    private Model model ; 

    @FXML 
    private TextField nameField ; 

    @FXML 
    private void submit() { 
     model.addName(nameField.getText()); 
     close(); 
    } 

    @FXML 
    private void close() { 
     nameField.getScene().getWindow().hide(); 
    } 
} 

は2つのFXMLファイルは、彼らがappパッケージの両方である(以下のとおりです。私はこれらをコード化された方法での唯一の本当の要件は、ということです対応するコントローラークラスと同じパッケージ内にある必要があります)。

Main.fxml:

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

<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.control.ListView?> 
<?import javafx.scene.layout.HBox?> 
<?import javafx.geometry.Insets?> 
<?import javafx.scene.control.Button?> 

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.MainController"> 
    <center> 
     <ListView fx:id="listView" /> 
    </center> 
    <bottom> 
     <HBox alignment="CENTER"> 
      <padding> 
       <Insets top="5" right="5" left="5" bottom="5" /> 
      </padding> 
      <Button text="Add..." onAction="#showAddDialog" /> 
     </HBox> 
    </bottom> 
</BorderPane> 

AddNameDialog。FXML:あなたは本当にCDIはあなたを提供させたい場合は

<?xml version="1.0" encoding="UTF-8"?> 
<beans 
     xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" 
     bean-discovery-mode="all"> 
</beans> 

package app; 

import java.io.IOException; 

import org.jboss.weld.environment.se.Weld; 
import org.jboss.weld.environment.se.WeldContainer; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class Main extends Application { 

    private Weld weld ; 
    private WeldContainer container ; 

    @Override 
    public void init() { 
     weld = new Weld(); 
     container = weld.initialize(); 
    } 

    @Override 
    public void stop() { 
     weld.shutdown(); 
    } 

    @Override 
    public void start(Stage primaryStage) throws IOException { 
     FXMLLoader loader = new FXMLLoader(MainController.class.getResource("Main.fxml")); 
     loader.setControllerFactory(container.select(CDIControllerFactory.class).get()); 
     Scene scene = new Scene(loader.load(), 600, 600); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

そしてもちろんのCDIの設定クラス、META-INF/beans.xml

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

<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.control.ListView?> 
<?import javafx.scene.layout.HBox?> 
<?import javafx.geometry.Insets?> 
<?import javafx.scene.control.Button?> 

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="app.MainController"> 
    <center> 
     <ListView fx:id="listView" /> 
    </center> 
    <bottom> 
     <HBox alignment="CENTER"> 
      <padding> 
       <Insets top="5" right="5" left="5" bottom="5" /> 
      </padding> 
      <Button text="Add..." onAction="#showAddDialog" /> 
     </HBox> 
    </bottom> 
</BorderPane> 

ここではアプリケーションクラスですステージでは、あなたがすることができますが、私は実際にそれによって得ることがたくさんあるとは思わない。しかし、例えば。

public class MainController { 

    @Inject 
    private Model model ; 
    @Inject 
    private CDIControllerFactory controllerFactory ; 

    @Inject 
    @ModalStage 
    private Stage addNameDialogStage ; 

    @FXML 
    private ListView<String> listView ; 

    @FXML 
    private void initialize() { 
     listView.setItems(model.getNames()); 
    } 

    @FXML 
    private void showAddDialog() throws IOException { 
     FXMLLoader loader = new FXMLLoader(AddNameController.class.getResource("AddNameDialog.fxml")); 
     loader.setControllerFactory(controllerFactory); 
     Scene scene = new Scene(loader.load()); 
     addNameDialogStage.setScene(scene); 
     addNameDialogStage.show(); 
    } 
} 

は、他の施設あなたがありますように、あなたのMainControllerが見えるかもしれません、その後

package app; 

import javax.enterprise.inject.Produces; 

import javafx.stage.Modality; 
import javafx.stage.Stage; 

public class StageProducer { 

    @Produces 
    public Stage stage() { 
     return new Stage(); 
    } 

    @Produces 
    @ModalStage 
    public Stage modalStage() { 
     Stage stage = stage(); 
     stage.initModality(Modality.APPLICATION_MODAL); 
     return stage ; 
    } 
} 

とを:あなたがモーダルと非モーダルのステージを提供することができます

package app; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

import javax.inject.Qualifier; 

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.FIELD, ElementType.METHOD, 
     ElementType.TYPE, ElementType.PARAMETER}) 
public @interface ModalStage { } 

:あなたのような何かを行うことができますこれに簡単に組み込むことができます。リソース名からFXMLをロードするためのクラスを提供しています。コントローラーファクトリーを既に組み込んでいます。

関連する問題