전달 매개 변수 JavaFX FXML


194

javafx에서 보조 창에 매개 변수를 전달하려면 어떻게해야합니까? 해당 컨트롤러와 통신하는 방법이 있습니까?

예 : 사용자가 고객을 선택하면 고객 TableView정보를 보여주는 새 창이 열립니다.

Stage newStage = new Stage();
try 
{
    AnchorPane page = (AnchorPane) FXMLLoader.load(HectorGestion.class.getResource(fxmlResource));
    Scene scene = new Scene(page);
    newStage.setScene(scene);
    newStage.setTitle(windowTitle);
    newStage.setResizable(isResizable);
    if(showRightAway) 
    {
        newStage.show();
    }
}

newStage새 창이 될 것입니다. 문제는 컨트롤러에 고객 정보를 어디에서 찾을 것인지 알려주는 방법을 찾을 수 없다는 것입니다 (id를 매개 변수로 전달하여).

어떤 아이디어?


이것이 작동하는지 확인하십시오 : stackoverflow.com/questions/14370183/…
Dynelight

@Alvaro : 솔루션을 얻었습니까? 당신은 매개 변수를 전달할 수 있습니까? 한 컨트롤러에서 다른 컨트롤러 파일로?
Java Man

3
예. jewelsea는 책 수준의 설명을했습니다. 그래서 제가 그의 대답을 받아 들였습니다
Alvaro

답변:


276

권장 접근법

이 답변은 FXML 컨트롤러에 매개 변수를 전달하기위한 다양한 메커니즘을 열거합니다.

소규모 응용 프로그램의 경우 호출자에서 컨트롤러로 직접 매개 변수를 전달하는 것이 좋습니다. 간단하고 간단하며 추가 프레임 워크가 필요하지 않습니다.

더 크고 복잡한 응용 프로그램의 경우 응용 프로그램 내에서 Dependency Injection 또는 Event Bus 메커니즘 을 사용하려는 경우 조사하는 것이 좋습니다 .

발신자에서 컨트롤러로 직접 매개 변수 전달

FXML 로더 인스턴스에서 컨트롤러를 검색하고 컨트롤러에서 메서드를 호출하여 필요한 데이터 값으로 초기화하여 사용자 지정 데이터를 FXML 컨트롤러로 전달합니다.

다음 코드와 같은 것 :

public Stage showCustomerDialog(Customer customer) {
  FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
      "customerDialog.fxml"
    )
  );

  Stage stage = new Stage(StageStyle.DECORATED);
  stage.setScene(
    new Scene(
      (Pane) loader.load()
    )
  );

  CustomerDialogController controller = 
    loader.<CustomerDialogController>getController();
  controller.initData(customer);

  stage.show();

  return stage;
}

...

class CustomerDialogController {
  @FXML private Label customerName;
  void initialize() {}
  void initData(Customer customer) {
    customerName.setText(customer.getName());
  }
}

새로운 FXMLLoader는 샘플 코드에 표시된대로 구성됩니다 new FXMLLoader(location). 위치는 URL이며 다음과 같은 방법으로 FXML 리소스에서 이러한 URL을 생성 할 수 있습니다.

new FXMLLoader(getClass().getResource("sample.fxml"));

FXMLLoader에서 정적로드 기능을 사용하지 않도록주의하십시오. 그렇지 않으면 로더 인스턴스에서 컨트롤러를 가져올 수 없습니다.

FXMLLoader 인스턴스 자체는 도메인 개체에 대해 전혀 알지 못합니다. 대신 응용 프로그램 특정 도메인 개체를 FXMLLoader 생성자로 직접 전달하지 않습니다.

  1. 지정된 위치에서 fxml 마크 업을 기반으로 FXMLLoader 생성
  2. FXMLLoader 인스턴스에서 컨트롤러를 가져옵니다.
  3. 검색된 컨트롤러에서 메소드를 호출하여 컨트롤러에 도메인 오브젝트에 대한 참조를 제공하십시오.

이 블로그 (다른 작가의)는 대안이지만 유사한 예제를 제공 합니다.

FXMLLoader에서 컨트롤러 설정

CustomerDialogController dialogController = 
    new CustomerDialogController(param1, param2);

FXMLLoader loader = new FXMLLoader(
    getClass().getResource(
        "customerDialog.fxml"
    )
);
loader.setController(dialogController);

Pane mainPane = (Pane) loader.load();

호출자에서 원하는 매개 변수를 컨트롤러 생성자로 전달하여 코드로 새 컨트롤러를 구성 할 수 있습니다. 컨트롤러를 생성 한 후에 는 인스턴스 메서드 를 호출 하기 전에 FXMLLoader 인스턴스에서 컨트롤러를 설정할 수 있습니다 .load()

로더 (JavaFX 2.x)에서 제어기를 설정하기 fx:controller위해 fxml 파일에서 속성을 정의 할 수도 없습니다 .

fx:controllerFXML 의 정의에 대한 제한으로 인해 컨트롤러를 FXMLLoader로 설정하는 대신 FXMLLoader에서 컨트롤러를 얻는 것을 개인적으로 선호합니다.

컨트롤러가 외부 정적 메소드에서 매개 변수를 검색하도록하기

이 메소드는 Controller.java 파일의 Javafx 2.0 How-to Application.getParameters ()에 대한 Sergey의 답변으로 예시됩니다 .

의존성 주입 사용

FXMLLoader는 Guice, Spring 또는 Java EE CDI와 같은 종속성 주입 시스템을 지원하여 FXMLLoader에서 사용자 정의 컨트롤러 팩토리를 설정할 수 있습니다. 이는 각각의 의존성 주입 시스템에 의해 주입 된 의존성 값으로 컨트롤러 인스턴스를 생성하는 데 사용할 수있는 콜백을 제공합니다.

Spring을 사용한 JavaFX 애플리케이션 및 컨트롤러 종속성 주입의 예는 다음에 대한 답변으로 제공됩니다.

정말로 멋진 깨끗한 의존성 주입 방식이 예시된다 afterburner.fx 워크 시료와 공기 해킹 어플리케이션 용도 것이있다. afterburner.fx는 JEE6 javax.inject 를 사용하여 종속성 주입을 수행합니다.

이벤트 버스 이용

원래 FXML 사양 작성자이자 구현자인 Greg Brown 은 FXML 인스턴스화 된 컨트롤러와 다른 응용 프로그램 논리 간의 통신을 위해 Guava EventBus 와 같은 이벤트 버스 사용을 고려할 것을 제안 합니다.

EventBus는 POJO가 서로 참조하지 않고도 JVM의 어느 곳에서나 서로 통신 할 수 있도록하는 주석이있는 단순하지만 강력한 발행 / 구독 API입니다.

후속 Q & A

첫 번째 방법에서는 왜 Stage를 반환합니까? show () 명령을 이미 제공했기 때문에이 메소드도 무효가 될 수 있습니다. 귀국 바로 전에;. 스테이지를 반환하여 사용을 계획하는 방법

문제에 대한 기능적 솔루션입니다. 스테이지는 showCustomerDialog함수 에서 반환 되어 나중에 기본 창에서 버튼 클릭을 기반으로 스테이지를 숨기는 등의 작업을 수행하려는 외부 클래스에 의해 참조를 저장할 수 있습니다. 대체 객체 지향 솔루션은 CustomerDialog 객체 내부의 기능 및 스테이지 참조를 캡슐화하거나 CustomerDialog extend Stage를 가질 수 있습니다. FXML, 컨트롤러 및 모델 데이터를 캡슐화하는 사용자 정의 대화 상자에 대한 객체 지향 인터페이스의 전체 예는이 답변의 범위를 벗어 났지만 누구나 블로그 게시물을 작성하려는 경향이 있습니다.


@dzim 이라는 StackOverflow 사용자가 제공 한 추가 정보

스프링 부트 의존성 주입 예제

"The Spring Boot Way"를 수행하는 방법에 대한 질문에 JavaFX 2에 대한 토론이있었습니다. 이 접근 방식은 2016 년 3 월 Spring Boot v1.3.3에서 여전히 유효하고 테스트되었습니다 .RELEASE : https://stackoverflow.com/a/36310391/1281217


때로는 결과를 발신자에게 다시 전달할 수도 있습니다.이 경우 관련 질문에 대한 답변을 확인할 수 있습니다.


FXMLLoader 생성자는 URL을 매개 변수로만 사용합니다. FXMLLoader를 인스턴스화하는 올바른 방법은 무엇입니까?
Alvaro

1
상태를 언급 이벤트 버스 웹 사이트, "업데이트 2천13분의 3 다음 EventBus은 ... 사라 오래된있다"
J 것이다

1
DataFX 컨트롤러 프레임 워크는 FXML 컨트롤러에 대한 일부 인젝션 지원을 제공합니다. guigarage.com/2013/12/datafx-controller-framework-preview
Hendrik Ebbers

2
@Anarkie
jewelsea

7
JavaFx 에서이 작은 작업을 수행하는 데 간단한 것이 있습니까? 생성자와 javafx에 데이터를 전달하는 매우 일반적인 기능은 하나의 이름이나 하나의 값을 보내려면이 모든 것들이 함께 필요합니까?
Zahan Safallwa

13

나는 이것이 매우 오래된 게시물이라는 것을 알고 있으며 이미 훌륭한 답변을 얻었지만 그러한 접근법 중 하나를 보여주기 위해 간단한 MCVE를 만들고 새로운 코더가 개념을 실제로 볼 수있는 방법을 원했습니다.

이 예에서는 5 개의 파일을 사용합니다.

  1. Main.java- 응용 프로그램을 시작하고 첫 번째 컨트롤러를 호출하는 데 사용됩니다.
  2. Controller1.java- 첫 번째 FXML 레이아웃의 컨트롤러입니다.
  3. Controller2.java- 두 번째 FXML 레이아웃의 컨트롤러입니다.
  4. Layout1.fxml- 첫 번째 장면의 FXML 레이아웃입니다.
  5. Layout2.fxml- 두 번째 장면의 FXML 레이아웃입니다.

모든 파일은이 게시물의 맨 아래에 전체적으로 나열됩니다.

목표는 : 에서 값을 전달 보여주기 Controller1Controller2반대의 경우도 마찬가지.

프로그램 흐름 :

  • 첫 번째 장면에는 TextField, a Button및 a가 포함 Label됩니다. 를 Button클릭하면에 입력 한 텍스트를 포함하여 두 번째 창이로드되어 표시됩니다 TextField.
  • 두 번째 장면에는 TextField, a Button및 a도 Label있습니다. 는 Label에 입력 한 텍스트가 표시됩니다 TextField첫 번째 장면에있다.
  • 두 번째 장면에 텍스트를 입력하고을 TextField클릭하면 Button첫 번째 장면 Label이 업데이트되어 입력 한 텍스트가 표시됩니다.

이것은 매우 간단한 시연이며 일부 개선의 여지가 있지만 개념을 매우 명확하게 만들어야합니다.

또한 코드 자체에는 무슨 일이 일어나고 있는지에 대한 몇 가지 세부 사항이 설명되어 있습니다.

코드

Main.java :

import javafx.application.Application;
import javafx.stage.Stage;

public class Main extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        // Create the first controller, which loads Layout1.fxml within its own constructor
        Controller1 controller1 = new Controller1();

        // Show the new stage
        controller1.showStage();

    }
}

Controller1.java :

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

import java.io.IOException;

public class Controller1 {

    // Holds this controller's Stage
    private final Stage thisStage;

    // Define the nodes from the Layout1.fxml file. This allows them to be referenced within the controller
    @FXML
    private TextField txtToSecondController;
    @FXML
    private Button btnOpenLayout2;
    @FXML
    private Label lblFromController2;

    public Controller1() {

        // Create the new stage
        thisStage = new Stage();

        // Load the FXML file
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout1.fxml"));

            // Set this class as the controller
            loader.setController(this);

            // Load the scene
            thisStage.setScene(new Scene(loader.load()));

            // Setup the window/stage
            thisStage.setTitle("Passing Controllers Example - Layout1");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Show the stage that was loaded in the constructor
     */
    public void showStage() {
        thisStage.showAndWait();
    }

    /**
     * The initialize() method allows you set setup your scene, adding actions, configuring nodes, etc.
     */
    @FXML
    private void initialize() {

        // Add an action for the "Open Layout2" button
        btnOpenLayout2.setOnAction(event -> openLayout2());
    }

    /**
     * Performs the action of loading and showing Layout2
     */
    private void openLayout2() {

        // Create the second controller, which loads its own FXML file. We pass a reference to this controller
        // using the keyword [this]; that allows the second controller to access the methods contained in here.
        Controller2 controller2 = new Controller2(this);

        // Show the new stage/window
        controller2.showStage();

    }

    /**
     * Returns the text entered into txtToSecondController. This allows other controllers/classes to view that data.
     */
    public String getEnteredText() {
        return txtToSecondController.getText();
    }

    /**
     * Allows other controllers to set the text of this layout's Label
     */
    public void setTextFromController2(String text) {
        lblFromController2.setText(text);
    }
}

Controller2.java :

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

import java.io.IOException;

public class Controller2 {

    // Holds this controller's Stage
    private Stage thisStage;

    // Will hold a reference to the first controller, allowing us to access the methods found there.
    private final Controller1 controller1;

    // Add references to the controls in Layout2.fxml
    @FXML
    private Label lblFromController1;
    @FXML
    private TextField txtToFirstController;
    @FXML
    private Button btnSetLayout1Text;

    public Controller2(Controller1 controller1) {
        // We received the first controller, now let's make it usable throughout this controller.
        this.controller1 = controller1;

        // Create the new stage
        thisStage = new Stage();

        // Load the FXML file
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout2.fxml"));

            // Set this class as the controller
            loader.setController(this);

            // Load the scene
            thisStage.setScene(new Scene(loader.load()));

            // Setup the window/stage
            thisStage.setTitle("Passing Controllers Example - Layout2");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Show the stage that was loaded in the constructor
     */
    public void showStage() {
        thisStage.showAndWait();
    }

    @FXML
    private void initialize() {

        // Set the label to whatever the text entered on Layout1 is
        lblFromController1.setText(controller1.getEnteredText());

        // Set the action for the button
        btnSetLayout1Text.setOnAction(event -> setTextOnLayout1());
    }

    /**
     * Calls the "setTextFromController2()" method on the first controller to update its Label
     */
    private void setTextOnLayout1() {
        controller1.setTextFromController2(txtToFirstController.getText());
    }

}

Layout1.fxml :

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <VBox alignment="CENTER" spacing="10.0">
        <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
        </padding>
        <Label style="-fx-font-weight: bold;" text="This is Layout1!"/>
        <HBox alignment="CENTER_LEFT" spacing="10.0">
            <Label text="Enter Text:"/>
            <TextField fx:id="txtToSecondController"/>
            <Button fx:id="btnOpenLayout2" mnemonicParsing="false" text="Open Layout2"/>
        </HBox>
        <VBox alignment="CENTER">
            <Label text="Text From Controller2:"/>
            <Label fx:id="lblFromController2" text="Nothing Yet!"/>
        </VBox>
    </VBox>
</AnchorPane>

Layout2.fxml :

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <VBox alignment="CENTER" spacing="10.0">
        <padding>
            <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
        </padding>
        <Label style="-fx-font-weight: bold;" text="Welcome to Layout 2!"/>
        <VBox alignment="CENTER">
            <Label text="Text From Controller1:"/>
            <Label fx:id="lblFromController1" text="Nothing Yet!"/>
        </VBox>
        <HBox alignment="CENTER_LEFT" spacing="10.0">
            <Label text="Enter Text:"/>
            <TextField fx:id="txtToFirstController"/>
            <Button fx:id="btnSetLayout1Text" mnemonicParsing="false" text="Set Text on Layout1"/>
        </HBox>
    </VBox>
</AnchorPane>

1
FXML 파일에서 컨트롤러를 설정할 수 있습니까? 라인을 제거하고 loader.setController(this)FXML 파일에 컨트롤러를 추가하면 응용 프로그램이 중단됩니다
Halfacht

1
컨트롤러 자체에서 FXML을로드하면 아닙니다. 예를 들어 Main 클래스에서 FXML을로드하면 FXML 파일에서 컨트롤러를 정의하고 다음을 사용하여 참조를 얻을 수 있습니다.loader.getController()
Zephyr

마지막으로 해결책을 찾았습니다. 나는 그것을 프로젝트에 구현했으며 이제는 두 창을 동시에 열어서 먼저 모달로 만들려고합니다. 불행히도 하나만 열립니다. 누구든지 도와 줄 수 있습니까?
jabba

8

javafx.scene.Node 클래스에는 setUserData (Object) 및 Object getUserData () 메소드 쌍이 있습니다.

노드에 정보를 추가하는 데 사용할 수 있습니다.

따라서 page.setUserData (info);를 호출 할 수 있습니다.

정보가 설정되어 있으면 컨트롤러가 확인할 수 있습니다. 또한 필요한 경우 뒤로 전달 데이터 전송에 ObjectProperty를 사용할 수 있습니다.

http://docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html 문서를 참조 하십시오. "첫 번째 버전에서 handleButtonAction ()은 @FXML로 태그 지정됩니다. 컨트롤러의 문서에 정의 된 마크 업이이를 호출 할 수 있도록합니다. 두 번째 예에서는 버튼 필드에 주석을 달아 로더가 값을 설정할 수 있도록합니다. initialize () 메소드도 비슷하게 주석이 달립니다. "

따라서 제어기를 노드와 연관시키고 사용자 데이터를 노드로 설정해야합니다.


Stage.getScene ()-> Scene.getRoot ()-> Parent.getChildrenUnmodifiable ()을 사용한 재귀 검색 이것은 매우 더러운 방법입니다. 누군가가 더 나은 제안을 할 수 있다면 그것은 좋을 것입니다.
Alexander Kirov

Stage.getScene (). getRoot ()가 올바른 방법 인 것 같습니다! 감사합니다
Alvaro

7

다음은 네임 스페이스를 통해 매개 변수를 fxml 문서에 전달하는 예제입니다.

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1">
    <BorderPane>
        <center>
            <Label text="$labelText"/>
        </center>
    </BorderPane>
</VBox>

External Text네임 스페이스 변수의 값 을 정의하십시오 labelText.

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

import java.io.IOException;

public class NamespaceParameterExampleApplication extends Application {

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

    @Override
    public void start(Stage primaryStage) throws IOException {
        final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("namespace-parameter-example.fxml"));

        fxmlLoader.getNamespace()
                  .put("labelText", "External Text");

        final Parent root = fxmlLoader.load();

        primaryStage.setTitle("Namespace Parameter Example");
        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();
    }
}

예를 들면 : 일부 키가 내부적으로 사용되는 것을 주목해야한다 FXMLLoader.CONTROLLER_KEYWORD, FXMLLoader.LOCATION_KEY, FXMLLoader.RESOURCES_KEY임의의 문자열에 대한 값으로 사용 fx:id속성.
fabian

고마워요. 다른 장면은 메인 장면에 이전에 표시된 텍스트를 보여주는 컨테이너 일뿐입니다. 이제 Namepace 변수를 통해 컨텐츠를 초기화하여 여러 위치에서 재사용 할 수있는 하나의 fxml을 가질 수 있습니다. 새로운 메소드를 만들거나 생성자 또는 이니셜 라이저를 변경할 필요가 없었습니다. FXML에 변수를 추가하고 메인 컨트롤러의 fxmloader 코드에 한 줄만 추가하면됩니다.
SystemsInCode

4

이 작동합니다 ..

전달하는 값을 처음 인쇄 할 때 null이된다는 것을 기억하십시오. 창을로드 한 후에는 다른 구성 요소에 대해 코딩하려는 모든 항목에 동일하게 사용할 수 있습니다.

첫 컨트롤러

try {
    Stage st = new Stage();
    FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/inty360/free/form/MainOnline.fxml"));

    Parent sceneMain = loader.load();

    MainOnlineController controller = loader.<MainOnlineController>getController();
    controller.initVariable(99L);

    Scene scene = new Scene(sceneMain);
    st.setScene(scene);
    st.setMaximized(true);
    st.setTitle("My App");
    st.show();
} catch (IOException ex) {
    Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex);
}

다른 컨트롤러

public void initVariable(Long id_usuario){
    this.id_usuario = id_usuario;
    label_usuario_nombre.setText(id_usuario.toString());
}

1
이것은 첫 번째 컨트롤러에서 두 번째 컨트롤러로 매개 변수를 전달할 때 작동하지만 두 번째에서 첫 번째 컨트롤러로 매개 변수를 전달하는 방법은 first.fxml 이로 드 된 후를 의미합니다.
Menai Ala Eddine-알라딘

@XlintXms는 추가 질문을 다루는 컨트롤러 A에서 B로 전달되는 관련 질문 JavaFX FXML 매개 변수를 봅니다 .
jewelsea

2

하나의 컨텍스트 클래스를 작성해야합니다.

public class Context {
    private final static Context instance = new Context();
    public static Context getInstance() {
        return instance;
    }

    private Connection con;
    public void setConnection(Connection con)
    {
        this.con=con;
    }
    public Connection getConnection() {
        return con;
    }

    private TabRoughController tabRough;
    public void setTabRough(TabRoughController tabRough) {
        this.tabRough=tabRough;
    }

    public TabRoughController getTabRough() {
        return tabRough;
    }
}

초기화를 사용하여 컨트롤러 인스턴스를 설정해야합니다.

Context.getInstance().setTabRough(this);

그리고 당신은 그것을 사용하여 전체 응용 프로그램에서 사용할 수 있습니다

TabRoughController cont=Context.getInstance().getTabRough();

이제 전체 애플리케이션에서 모든 컨트롤러에 매개 변수를 전달할 수 있습니다.


우리는이 접근법을 사용하며 훌륭하게 작동합니다. 나는 생성자 내부 또는 initialize 메소드에있는 데이터에 접근 할 수 있고 데이터가 생성 된 후에 컨트롤러에 데이터를 설정할 필요가 없다
Bob

1

그래 넌 할수있어.
첫 번째 컨트롤러를 추가해야합니다.

YourController controller = loader.getController();     
controller.setclient(client);

그런 다음 두 번째 클라이언트에서 클라이언트를 선언 한 다음 컨트롤러 하단에서 선언하십시오.

public void setclien(Client c) {
    this.client = c;
}

0

다음은 Guice에서 주입 한 컨트롤러를 사용하는 예입니다.

/**
 * Loads a FXML file and injects its controller from the given Guice {@code Provider}
 */
public abstract class GuiceFxmlLoader {

   public GuiceFxmlLoader(Stage stage, Provider<?> provider) {
      mStage = Objects.requireNonNull(stage);
      mProvider = Objects.requireNonNull(provider);
   }

   /**
    * @return the FXML file name
    */
   public abstract String getFileName();

   /**
    * Load FXML, set its controller with given {@code Provider}, and add it to {@code Stage}.
    */
   public void loadView() {
      try {
         FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource(getFileName()));
         loader.setControllerFactory(p -> mProvider.get());
         Node view = loader.load();
         setViewInStage(view);
      }
      catch (IOException ex) {
         LOGGER.error("Failed to load FXML: " + getFileName(), ex);
      }
   }

   private void setViewInStage(Node view) {
      BorderPane pane = (BorderPane)mStage.getScene().getRoot();
      pane.setCenter(view);
   }

   private static final Logger LOGGER = Logger.getLogger(GuiceFxmlLoader.class);

   private final Stage mStage;
   private final Provider<?> mProvider;
}

로더의 구체적인 구현은 다음과 같습니다.

public class ConcreteViewLoader extends GuiceFxmlLoader {

   @Inject
   public ConcreteViewLoader(Stage stage, Provider<MyController> provider) {
      super(stage, provider);
   }

   @Override
   public String getFileName() {
      return "my_view.fxml";
   }
}

이 예제는 스테이지에서 장면의 루트 인 BoarderPane의 중심으로 뷰를로드합니다. 이것은 예제 (내 특정 사용 사례의 구현 세부 사항)와 관련이 없지만 일부는 유용 할 수 있으므로 그대로두기로 결정했습니다.


-1

공개 관찰 가능 목록을 사용하여 공개 데이터를 저장하거나 공개 설정 기 메소드를 작성하여 데이터를 저장하고 해당 제어기에서 검색 할 수 있습니다.


-3

왜 6 살짜리 질문에 대답합니까?
프로그래밍 언어와 함께 작동하는 가장 기본적인 개념 중 하나는 하나의 창 (창, 양식 또는 페이지)에서 다른 창으로 이동하는 방법입니다. 또한이 탐색을 수행하는 동안 개발자는 종종 하나의 창 (창, 양식 또는 페이지)에서 데이터를 전달하고 전달 된 데이터를 표시하거나 사용하려고합니다.
대부분의 답변은 훌륭한 예제에 대한 좋은 예를 제공하지만이를 달성하는 방법을 제안합니다. 노치 나 두 개 또는 세
우리는 세 가지 (창, 폼 또는 페이지)를 탐색하고 (창, 폼 또는 페이지)의 주위에 데이터를 전달하기 위해 정적 변수의 개념을 사용하기 때문에 우리는 세 가지를 말했다
우리는 또한 동안 코드를 만드는 몇 가지 결정이 포함됩니다 우리는 탐색

public class Start extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        // This is MAIN Class which runs first
        Parent root = FXMLLoader.load(getClass().getResource("start.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.setResizable(false);// This sets the value for all stages
        stage.setTitle("Start Page"); 
        stage.show();
        stage.sizeToScene();
    }

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

컨트롤러 시작

public class startController implements Initializable {

@FXML Pane startPane,pageonePane;
@FXML Button btnPageOne;
@FXML TextField txtStartValue;
public Stage stage;
public static int intSETonStartController;
String strSETonStartController;

@FXML
private void toPageOne() throws IOException{

    strSETonStartController = txtStartValue.getText().trim();


        // yourString != null && yourString.trim().length() > 0
        // int L = testText.length();
        // if(L == 0){
        // System.out.println("LENGTH IS "+L);
        // return;
        // }
        /* if (testText.matches("[1-2]") && !testText.matches("^\\s*$")) 
           Second Match is regex for White Space NOT TESTED !
        */

        String testText = txtStartValue.getText().trim();
        // NOTICE IF YOU REMOVE THE * CHARACTER FROM "[1-2]*"
        // NO NEED TO CHECK LENGTH it also permited 12 or 11 as valid entry 
        // =================================================================
        if (testText.matches("[1-2]")) {
            intSETonStartController = Integer.parseInt(strSETonStartController);
        }else{
            txtStartValue.setText("Enter 1 OR 2");
            return;
        }

        System.out.println("You Entered = "+intSETonStartController);
        stage = (Stage)startPane.getScene().getWindow();// pane you are ON
        pageonePane = FXMLLoader.load(getClass().getResource("pageone.fxml"));// pane you are GOING TO
        Scene scene = new Scene(pageonePane);// pane you are GOING TO
        stage.setScene(scene);
        stage.setTitle("Page One"); 
        stage.show();
        stage.sizeToScene();
        stage.centerOnScreen();  
}

private void doGET(){
    // Why this testing ?
    // strSENTbackFROMPageoneController is null because it is set on Pageone
    // =====================================================================
    txtStartValue.setText(strSENTbackFROMPageoneController);
    if(intSETonStartController == 1){
      txtStartValue.setText(str);  
    }
    System.out.println("== doGET WAS RUN ==");
    if(txtStartValue.getText() == null){
       txtStartValue.setText("");   
    }
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    // This Method runs every time startController is LOADED
     doGET();
}    
}

1 페이지 컨트롤러

public class PageoneController implements Initializable {

@FXML Pane startPane,pageonePane,pagetwoPane;
@FXML Button btnOne,btnTwo;
@FXML TextField txtPageOneValue;
public static String strSENTbackFROMPageoneController;
public Stage stage;

    @FXML
private void onBTNONE() throws IOException{

        stage = (Stage)pageonePane.getScene().getWindow();// pane you are ON
        pagetwoPane = FXMLLoader.load(getClass().getResource("pagetwo.fxml"));// pane you are GOING TO
        Scene scene = new Scene(pagetwoPane);// pane you are GOING TO
        stage.setScene(scene);
        stage.setTitle("Page Two"); 
        stage.show();
        stage.sizeToScene();
        stage.centerOnScreen();
}

@FXML
private void onBTNTWO() throws IOException{
    if(intSETonStartController == 2){
        Alert alert = new Alert(AlertType.CONFIRMATION);
        alert.setTitle("Alert");
        alert.setHeaderText("YES to change Text Sent Back");
        alert.setResizable(false);
        alert.setContentText("Select YES to send 'Alert YES Pressed' Text Back\n"
                + "\nSelect CANCEL send no Text Back\r");// NOTE this is a Carriage return\r
        ButtonType buttonTypeYes = new ButtonType("YES");
        ButtonType buttonTypeCancel = new ButtonType("CANCEL", ButtonData.CANCEL_CLOSE);

        alert.getButtonTypes().setAll(buttonTypeYes, buttonTypeCancel);

        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == buttonTypeYes){
            txtPageOneValue.setText("Alert YES Pressed");
        } else {
            System.out.println("canceled");
            txtPageOneValue.setText("");
            onBack();// Optional
        }
    }
}

@FXML
private void onBack() throws IOException{

    strSENTbackFROMPageoneController = txtPageOneValue.getText();
    System.out.println("Text Returned = "+strSENTbackFROMPageoneController);
    stage = (Stage)pageonePane.getScene().getWindow();
    startPane = FXMLLoader.load(getClass().getResource("start.fxml")); 
    Scene scene = new Scene(startPane);
    stage.setScene(scene);
    stage.setTitle("Start Page"); 
    stage.show();
    stage.sizeToScene();
    stage.centerOnScreen(); 
}

private void doTEST(){
    String fromSTART = String.valueOf(intSETonStartController);
    txtPageOneValue.setText("SENT  "+fromSTART);
    if(intSETonStartController == 1){
       btnOne.setVisible(true);
       btnTwo.setVisible(false);
       System.out.println("INTEGER Value Entered = "+intSETonStartController);  
    }else{
       btnOne.setVisible(false);
       btnTwo.setVisible(true);
       System.out.println("INTEGER Value Entered = "+intSETonStartController); 
    }  
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    doTEST();
}    

}

2 페이지 컨트롤러

public class PagetwoController implements Initializable {

@FXML Pane startPane,pagetwoPane;
public Stage stage;
public static String str;

@FXML
private void toStart() throws IOException{

    str = "You ON Page Two";
    stage = (Stage)pagetwoPane.getScene().getWindow();// pane you are ON
    startPane = FXMLLoader.load(getClass().getResource("start.fxml"));// pane you are GOING TO
    Scene scene = new Scene(startPane);// pane you are GOING TO
    stage.setScene(scene);
    stage.setTitle("Start Page"); 
    stage.show();
    stage.sizeToScene();
    stage.centerOnScreen();  
}

@Override
public void initialize(URL url, ResourceBundle rb) {

}    

}

아래는 모든 FXML 파일입니다

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane id="AnchorPane" fx:id="pagetwoPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="atwopage.PagetwoController">
   <children>
      <Button layoutX="227.0" layoutY="62.0" mnemonicParsing="false" onAction="#toStart" text="To Start Page">
         <font>
            <Font name="System Bold" size="18.0" />
         </font>
      </Button>
   </children>
</AnchorPane>

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane id="AnchorPane" fx:id="startPane" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="atwopage.startController">
   <children>
      <Label focusTraversable="false" layoutX="115.0" layoutY="47.0" text="This is the Start Pane">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <Button fx:id="btnPageOne" focusTraversable="false" layoutX="137.0" layoutY="100.0" mnemonicParsing="false" onAction="#toPageOne" text="To Page One">
         <font>
            <Font size="18.0" />
         </font>
      </Button>
      <Label focusTraversable="false" layoutX="26.0" layoutY="150.0" text="Enter 1 OR 2">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <TextField fx:id="txtStartValue" layoutX="137.0" layoutY="148.0" prefHeight="28.0" prefWidth="150.0" />
   </children>
</AnchorPane>

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane id="AnchorPane" fx:id="pageonePane" prefHeight="200.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="atwopage.PageoneController">
   <children>
      <Label focusTraversable="false" layoutX="111.0" layoutY="35.0" text="This is Page One Pane">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <Button focusTraversable="false" layoutX="167.0" layoutY="97.0" mnemonicParsing="false" onAction="#onBack" text="BACK">
         <font>
            <Font size="18.0" />
         </font></Button>
      <Button fx:id="btnOne" focusTraversable="false" layoutX="19.0" layoutY="97.0" mnemonicParsing="false" onAction="#onBTNONE" text="Button One" visible="false">
         <font>
            <Font size="18.0" />
         </font>
      </Button>
      <Button fx:id="btnTwo" focusTraversable="false" layoutX="267.0" layoutY="97.0" mnemonicParsing="false" onAction="#onBTNTWO" text="Button Two">
         <font>
            <Font size="18.0" />
         </font>
      </Button>
      <Label focusTraversable="false" layoutX="19.0" layoutY="152.0" text="Send Anything BACK">
         <font>
            <Font size="18.0" />
         </font>
      </Label>
      <TextField fx:id="txtPageOneValue" layoutX="195.0" layoutY="150.0" prefHeight="28.0" prefWidth="150.0" />
   </children>
</AnchorPane>


3
죄송합니다. 코드의 기능이나 수행 방식에 대한 설명없이 수백 줄의 코드를 게시하는 것은 그리 좋은 대답이 아닙니다. 또한 게시 한 코드가 매우 체계적으로 구성되어 따르기 어렵습니다.
Zephyr

요구하는 사람에게 무례 할 필요는 없습니다. 우리 모두 배우기 위해 여기 있습니다
Zeyad
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.