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을로드하기위한 클래스를 제공합니다. 이미 컨트롤러 팩토리를 통합하고 있습니다.
무언가에 스테이지를 삽입하는 것이 이상합니다. 제공 한 링크 중 어느 것도 DI 프레임 워크를 사용하여 스테이지를 관리하지 않습니다. 어떤 구성 요소가 무대에 의존하게 될지 아무 이유없이 볼 수 없습니다. 일반적으로 JavaFX의 종속성 주입 프레임 워크를 사용하여 모델과 서비스를 컨트롤러에 주입하고 모델과 서비스간에 다른 종속성을 설정합니다. –
James_D, 답장을 보내 주셔서 감사합니다. 문제는 모달 대화 상자를 표시하기 위해 새 스테이지가 필요하다는 것입니다. 따라서 문제는 어떻게 그 스테이지를 얻을 수 있습니까? ** 새로운 Stage() **를 호출하면 CDI 빈은 해당 스테이지의 컨트롤러에 주입되지 않습니다. –
새 무대를 만들면됩니다. DI 프레임 워크가 필요한 이유는 무엇입니까? –