web-dev-qa-db-ja.com

コントローラーを使用した複数のFXML、オブジェクトの共有

皆さん、こんばんわ、

このトピックに関する多くの投稿を既に見つけましたが、まだController1からController2にオブジェクトを渡すことができません。これを行う完全なチュートリアルまたはサンプルプロジェクトはどこかにありますか?

私は立ち往生するまで、私はここまで得ました:

国クラス

public class Country {
private SimpleStringProperty country = new SimpleStringProperty("");

//Constructor
public Country() {
}

//GETTERS
public String getCountry() {
    return country.get();
}

//SETTERS
public void setCountry(String value) {
    country.set(value);
}

@Override
public String toString() {
    return getCountry();
}
}

プログラムが起動すると、メインのFXMLがロードされます(Sample.fxml)。これには、トップパネルにメニューバーがあり、中央にコンテンツペインがあるボーダーペインが含まれています。初期化時に、新しいCountryオブジェクトを作成し、グローバル変数に保存します。メニュー項目をクリックすると、コンテンツペインに別のFXMLをロードするメソッドがあります。

SampleController.Java

public class SampleController implements Initializable {

@FXML
private Pane pContent;

private Country c;

@FXML
private void handleButtonAction(ActionEvent event) throws IOException {
    System.out.println(c); //this prints Belgium, which is correct

    URL url = getClass().getResource("Sub1.fxml");

    FXMLLoader fxmlloader = new FXMLLoader();
    fxmlloader.setLocation(url);
    fxmlloader.setBuilderFactory(new JavaFXBuilderFactory());

    pContent.getChildren().clear();
    pContent.getChildren().add((Node) fxmlloader.load(url.openStream()));
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    c = new Country();
    c.setCountry("Belgium");
}

public Country getCountryFromSampleController(){
    return c;
}
}

ここで、Sub1.fxmlがロードされたときにCountryオブジェクトをキャプチャしたいので、initialize()で国オブジェクトを取得する必要があります。

Sub1Controller.Java

public class Sub1Controller implements Initializable {

/**
 * Initializes the controller class.
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
    SampleController sp = new SampleController(); //I don't know how to fetch the original SampleController object
    System.out.println(sp.getCountryFromSampleController()); 
    //this prints null, which is ofcourse logical because I make a new SampleController object.         
}    
}

私が持っている質問、「元の」SampleControllerオブジェクトを取得してgetCountryFromRoot()メソッドを使用して値ベルギーのCountryオブジェクトをフェッチするにはどうすればよいですか?私は何時間もこの問題を探していて、これについてStackOverflowのすべての投稿を読んでいますが、ミッシングリンクが見つからないようです...任意の助け(できればこのコードで)を感謝します!

長い投稿でごめんなさい、私は理解できないだろう他の可能な限り完全にしようとしました...

27
Perneel

FXMLは MVCパターン の単純な形式です。 FXMLファイルはビューであり、コントローラーは明らかですが、何が見逃されていますか?モデル-現在のビューに関連するすべてのデータを保存する場所であり、コントローラー間で国データを共有するために使用できます。


1。モデルを導入するための可能なアプローチの1つは「コンテキスト」です。ケースを考えてみましょう。プロジェクト全体に対してモデルが1つしかないため、 Singleton の形式でグローバルコンテキストを使用できます。

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

    public static Context getInstance() {
        return instance;
    }

    private Country country = new Country();

    public Country currentCountry() {
        return country;
    }
}

SampleControllerには次の変更があります。

@Override
public void initialize(URL url, ResourceBundle rb) {
    Context.getInstance().currentCountry().setCountry("Belgium");
}

SubController1は同じ方法でアクセスできます:

@Override
public void initialize(URL url, ResourceBundle rb) {
    System.out.println(Context.getInstance().currentCountry().getCountry());
}

2。別の方法は、コンテキストをSubController1に渡してから、そのXMLをロードすることです。アプリケーションのグローバルモデルが必要ない場合は、より適切に機能します。したがって、同様のContextクラスを作成しますが、インスタンスフィールドはありません。

public class Sub1Controller implements Initializable {
    private Context context;
    public void setContext(Context context) {
        this.context = context;
        // initialize country dependent data here rather then in initialize()
    }
}

SampleControllerでコンテキストを設定:

Context currentContext = new Context();

@Override
public void initialize(URL url, ResourceBundle rb) {
    currentContext.currentCountry().setCountry("Belgium");
}

@FXML
private void handleButtonAction(ActionEvent event) throws IOException {
    URL url = getClass().getResource("Sub1.fxml");

    FXMLLoader fxmlloader = new FXMLLoader();
    fxmlloader.setLocation(url);
    fxmlloader.setBuilderFactory(new JavaFXBuilderFactory());

    pContent.getChildren().clear();
    pContent.getChildren().add((Node) fxmlloader.load(url.openStream()));
            // here we go
    ((Sub1Controller)fxmlloader.getController()).setContext(currentContext);
}
47
Sergey Grinev

dataFXのFlow APIを使用すると、CDIを使用してコントローラーインスタンスにデータを注入できます。

3
Hendrik Ebbers