2017-12-01 29 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

, 나는 그들이보다 더 주입 할 수 없기 때문에 현실 세계에서 작동하지 않습니다 본 모든 예제 하나의 스테이지 (primaryStage)가 있다면, 나는 어떻게해야할지 모르겠다.

그래서 나는

감사의 (... 예를 들어 모달 창에서 사용하는)은 하나 이상의 단계를 주입하기 위해 자바 FX/CDI 프로젝트에 가능하다면 알고 싶다!

+1

무언가에 스테이지를 삽입하는 것이 이상합니다. 제공 한 링크 중 어느 것도 DI 프레임 워크를 사용하여 스테이지를 관리하지 않습니다. 어떤 구성 요소가 무대에 의존하게 될지 아무 이유없이 볼 수 없습니다. 일반적으로 JavaFX의 종속성 주입 프레임 워크를 사용하여 모델과 서비스를 컨트롤러에 주입하고 모델과 서비스간에 다른 종속성을 설정합니다. –

+0

James_D, 답장을 보내 주셔서 감사합니다. 문제는 모달 대화 상자를 표시하기 위해 새 스테이지가 필요하다는 것입니다. 따라서 문제는 어떻게 그 스테이지를 얻을 수 있습니까? ** 새로운 Stage() **를 호출하면 CDI 빈은 해당 스테이지의 컨트롤러에 주입되지 않습니다. –

+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; 
    } 

} 

우리가 모든 컨트롤러와 함께 공유하고 싶은 모델 클래스 :

첫째, 그것은 적절한 컨트롤러를 유도 할 수있는 컨트롤러 공장을 노출 아마 좋은 생각이다. 우리가 하나 개의 인스턴스를 원하기 때문에, 우리는 그것을 @ApplicationScoped합니다

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

테스트 응용 프로그램이 단지 (이름 목록) 목록보기 및 대화 상자에서 새 이름을 추가하기위한 버튼이 있습니다. 그것은 FXMLLoader의 컨트롤러 공장을 사용하는 방법

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

참고 : 여기에 메인 컨트롤러입니다. 무대는 단지 "손으로"만들 수 있습니다.

다음은 새 이름을 추가하는 데 사용되는 대화 상자의 컨트롤러입니다. 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(); 
    } 
} 

두 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 :

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> 

응용 프로그램 클래스의 당신이 정말로 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> 

당신의 단계는, 당신은 할 수 있지만, 실제로 거기에서 많은 것을 얻을 수는 없다. 그러나 예를 들어

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을로드하기위한 클래스를 제공합니다. 이미 컨트롤러 팩토리를 통합하고 있습니다.