パラメータを渡す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コントローラーにパラメーターを渡すためのさまざまなメカニズムを列挙しています。

小さなアプリケーションの場合は、呼び出し元からコントローラーに直接パラメーターを渡すことを強くお勧めします。これはシンプルで簡単で、追加のフレームワークを必要としません。

大規模で複雑なアプリケーションの場合、アプリケーション内で依存性注入またはイベントバスメカニズムを使用するかどうかを調査することは価値があります。

呼び出し元からコントローラーに直接パラメーターを渡す

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は、FXMLLoaderでカスタムコントローラファクトリを設定できるようにすることで、Guice、Spring、Java EE CDIなどの依存性注入システムをサポートします。これにより、それぞれの依存性注入システムによって注入された依存値を持つコントローラーインスタンスを作成するために使用できるコールバックが提供されます。

SpringでのJavaFXアプリケーションとコントローラーの依存性注入の例は、以下の回答で提供されています。

本当に素敵でクリーンな依存性注入アプローチは、それを使用するサンプルのエアハックアプリケーションを備えたafterburner.fxフレームワークによって例示されています。afterburner.fxはJEE6のに依存しているjavax.inject依存性の注入を実行します。

イベントバスを使用する

元のFXML仕様の作成者および実装者であるGreg Brownは、FXMLのインスタンス化されたコントローラーと他のアプリケーションロジック間の通信のために、Guava EventBusなどのイベントバスの使用を検討することを提案しています。

EventBusは、POJOが相互に参照しなくてもJVM内の任意の場所で相互に通信できるようにする注釈を備えた、シンプルですが強力なパブリッシュ/サブスクライブAPIです。

フォローアップQ&A

最初の方法で、なぜステージに戻るのですか?show();コマンドをすでに与えているので、メソッドも無効になる可能性があります。リターンステージの直前;。ステージを返却して使用方法をどのように計画しますか

これは問題に対する機能的な解決策です。ステージはshowCustomerDialog関数から返されるので、後でメインウィンドウのボタンクリックに基づいてステージを非表示にするなど、何かを実行したい外部クラスによってステージへの参照を格納できます。別のオブジェクト指向ソリューションでは、機能とステージ参照をCustomerDialogオブジェクト内にカプセル化したり、CustomerDialogでステージを拡張したりできます。FXML、コントローラー、およびモデルデータをカプセル化するカスタムダイアログへのオブジェクト指向インターフェイスの完全な例は、この回答の範囲を超えていますが、作成を志向する人にとって価値のあるブログ投稿になる場合があります。


StackOverflowユーザーが@dzimという名前で提供する追加情報

Spring Boot Dependency Injectionの例

それをどのように行うかという質問「The Spring Boot Way」では、添付のパーマリンクで私が答えたJavaFX 2についての議論がありました。このアプローチはまだ有効であり、2016年3月にSpring Boot v1.3.3.RELEASEでテストされていますhttps ://stackoverflow.com/a/36310391/1281217


場合によっては、結果を呼び出し元に返したいことがあります。その場合、関連する質問への回答を確認できます。


FXMLLoaderコンストラクターはURLのみをパラメーターとして受け取ります。FXMLLoaderをインスタンス化する正しい方法は何ですか?
Alvaro 2013年

1
イベントバスのウェブサイトは、「2013
jは

1
DataFXコントローラフレームワークは、FXMLコントローラのためのいくつかの射出サポートを提供します。guigarage.com/2013/12/datafx-controller-framework-preview
ヘンドリック・Ebbers

2
@Anarkieのさらなる質問に答えるために回答するために追加のQ&Aセクションを追加しました
jewelsea

7
godshakeのために、JavaFxでこの小さな作業を行うために簡単なことはありますか?コンストラクタとjavafxでデータを渡すことは非常に一般的な機能であり、1つの名前または1つの値を送信するためだけに、この地獄が必要です。
Zahan Safallwa 2017

13

私はこれが非常に古い投稿であり、すでにいくつかの素晴らしい答えがあることを理解していますが、単純なMCVEを作成してそのようなアプローチの1つを示し、新しいプログラマーが実際のコンセプトをすばやく確認できるようにしたいと思いました。

この例では、5つのファイルを使用します。

  1. Main.java-アプリケーションを起動し、最初のコントローラーを呼び出すためだけに使用されます。
  2. Controller1.java-最初のFXMLレイアウトのコントローラー。
  3. Controller2.java -2番目のFXMLレイアウトのコントローラー。
  4. Layout1.fxml-最初のシーンのFXMLレイアウト。
  5. Layout2.fxml -2番目のシーンのFXMLレイアウト。

すべてのファイルは、この投稿の下部に全体がリストされています。

目標:からController1Controller2またはその逆に値を渡すことを示す。

プログラムの流れ:

  • 最初のシーンは含まれていTextFieldButtonLabel。をButtonクリックすると、2番目のウィンドウがロードされ、に入力されたテキストを含めて表示されますTextField
  • 2番目のシーンの中でもありTextFieldButtonLabel。にLabel入力したテキストがTextField最初のシーンに表示されます。
  • 2番目のシーンにテキストを入力して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

最後に私はなんとか解決策を見つけることができました。私はそれを自分のプロジェクトに実装し、両方のウィンドウを同時に開いて最初にモーダルにすることを試みています。残念ながら1つだけが開きます。誰かそれを手伝ってくれる?
ジャバ

8

javafx.scene.Nodeクラスには、メソッドsetUserData(Object)とオブジェクトgetUserData()のペアがあります

ノードに情報を追加するために使用できるもの。

したがって、page.setUserData(info);を呼び出すことができます。

コントローラーは、情報が設定されているかどうかを確認できます。また、必要に応じて、逆転送データ転送にObjectPropertyを使用できます。

ここでドキュメントを確認してください:http : //docs.oracle.com/javafx/2/api/javafx/fxml/doc-files/introduction_to_fxml.html「最初のバージョンでは、handleButtonAction()は@FXMLコントローラのドキュメントで定義されたマークアップが呼び出せるようにします。2番目の例では、ローダーが値を設定できるようにボタンフィールドに注釈が付けられています。initialize()メソッドにも同様に注釈が付けられています。

そのため、コントローラーをノードに関連付け、ユーザーデータをノードに設定する必要があります。


Stage.getScene()-> Scene.getRoot()-> Parent.getChildrenUnmodifiable()による再帰検索。これは非常に汚い方法です。誰かがより良いsmthを提案できるなら-それは素晴らしいでしょう。
Alexander Kirov 2013年

Stage.getScene()。getRoot()が正しい方法のようです!ありがとう
Alvaro 2013年

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_KEYWORDFXMLLoader.LOCATION_KEYFXMLLoader.RESOURCES_KEYおよびの値として使用任意の文字列fx:idの属性。
ファビアン

このおかげで、私のもう1つのシーンは、以前にメインシーンに表示されたテキストを表示するコンテナにすぎません。これで、Namepace変数を介してコンテンツを初期化することで、複数の場所で再利用できる1つのfxmlを作成できます。新しいメソッドを作成したり、コンストラクターやイニシャライザーを変更したりする必要はありませんでした。FXMLに変数を追加して、メインコントローラーのfxmloaderコードに1行追加するだけです。
SystemsInCode 2018年

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
これは、最初のコントローラーから2番目のコントローラーにパラメーターを渡すときに機能しますが、2番目のコントローラーから最初のコントローラーにパラメーターを渡す方法です。つまり、first.fxmlがロードされた後です。
Menai Ala Eddine-アラジン2017年

@XlintXmsは、コントローラーAからコントローラーBに渡されるJavaFX FXMLパラメーターに関連する質問を参照して、追加の質問に対処します。
-jewelsea

2

1つのコンテキストクラスを作成する必要があります。

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

次に、2つ目でクライアントを宣言し、次にコントローラーの下部で次のように宣言します。

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年前の質問に答えるのですか?
プログラミング言語を操作する最も基本的な概念の1つは、ウィンドウ(フォーム、ページ)間を移動する方法です。また、このナビゲーションを実行している間、開発者は1つ(ウィンドウ、フォーム、またはページ)からデータを渡し、渡されたデータを表示または使用する
ことを望みます。ノッチまたは2または3つが
、我々は3(ウィンドウ、フォームまたはページ)間を移動して(ウィンドウ、フォームまたはページ)を中心にデータを渡すために静的変数の概念を使用しますので、我々は3を言った
私たちは、また一方で、コードを作成するいくつかの意思決定が含まれます私たちはナビゲートします

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.