質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.11%

[JAVAFX]TextFiledに入力された値の取得方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 959

shibayun

score 10

 前提・実現したいこと

何度も質問すみません。
実現したい内容は下の画像になります。
イメージ説明

今作成しているプログラムは画面A、画面B、画面Aコントローラクラス、画面Bコントローラクラスにて構成されています。
画面AにはTextFieldとButton、画面BではTableViewがあり、Button押下で画面Bに遷移します。

画面遷移やdatabaseからのデータ取得をし単純にTableViewに表示することはできましたが、FXML内のTextFiledに値を入力し、他のコントローラクラスにその入力された値を渡す方法が分からず悩んでいます。
可能な方法がありましたらどうかご教授願います。

```

 試したこと

[画面Aクラス]puclic staticにてString型変数を宣言し、変数 = textfield名.getText(); 
→[画面BクラスS]System.out.print(画面Aクラス.変数); 結果は何も表示されませんでした。


追記:画面A
![イメージ説明](31b9b64b02af9b1ad8267c825446577f.png)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

ユーザーとの対話をするための小さな画面を一般にダイアログと呼びます。多分画面Aはダイアログとして設計できると思います。

ダイアログを実装するためには通常の画面(JavaFXではStage)と同様にもできます。質問者さんはおそらくそういうイメージをお持ちであろうと思います。しかしながら大抵のGUIライブラリーと同様JavaFXもダイアログを簡便に実装するための特化機能が用意されておりそちらを使う方がより簡単と思います。

JavaFXでのダイアログはjavafx.scene.control.Dialogというベースクラスおよびその派生として定義することが想定されていますが、本件のように文字列テキストの入力なら専用クラスjavafx.scene.control.TextInputDailogが用意されていますのでそれを使うのがよいと思います。

簡単な例を挙げてみますと以下のようになります。

TextInputDialog dialog = new TextInputDialog("") {
  {
    setTitle("filtering");
    setHeaderText("input filtering text");
  }
};
Optional<String> optInput = dialog.showAndWait();
if (!optInput.isPresent()) {
  // キャンセルが押された場合optInputは値を持たない
  System.out.println("cancelled");
} else {
  // OKが押された場合はoptInputは値を持ち、それはgetにより得られる。
  System.out.println("input text = " + optInput.get());
}

上記ではデフォルトから2点のみ動作を変えています。一つはダイアログタイトルで、もう一つはヘッダーテキストです。様々なカスタマイズをするためにはjavafx.control.Dialogの機能を調べるとやり方がわかってきますが、とりあえずはデフォルトの振る舞いがどのようになっているかを観察してみるとよいでしょう。

他のコントローラクラスにその入力された値を渡す方法が分からず悩んでいます。

ダイアログを用いる場合、ユーザーの入力結果はshowAndWaitメソッドの戻り値になるので、それを用いることになります。本件の場合、画面Bのコントローラーインスタンスへなんらかの方法で渡すのが自然と思います。渡し方は画面Bをどうやって生成・表示するかによって若干のバリエーションがありますが、FXMLとFXMLLoaderにより画面を生成する方法を用いるなら、以下のようにFXMLロード後にコントローラーインスタンスを取得しそこに定義したメソッドを通じて設定という流れが典型的な方法の一つだと思います。

FXMLLoader loader = new FXMLLoader(...);
loader.load();
ControllerB controllerB = loader.getController();
controllerB.setFilterText(optInput.get());

追記:
回答コメントから質問者さんの想定がダイアログではないようですので、各画面のStage, コントローラーを画面遷移の都度生成する前提に注意しつつ、画面遷移方法を考えてみました。以下の例は唯一の方法でもベストなものというわけではありません。やりかたには微妙なバリエーションがあるでしょう。つまり「ある画面から別の画面へ情報を引き渡す」実装例の一つです。

画面遷移メソッド(アプリケーションクラスに用意する例)

public class MyApp extends Application {
  private static MyApp app;

  public static MyApp getInstance() {
    return Objects.requireNonNull(app);
  }

  public MyApp() { app = this; }

  HashMap<Class<? extends Initializable>, String> fxmlMap = new HashMap<>();

  @Override
  public void start(Stage stage) {
    fxmlMap.put(AController.class, "A.fxml");
    fxmlMap.put(BController.class, "B.fxml");

    try {
      Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
      stage.setScene(new Scene(root));
      stage.show();
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

  public <C extends Initializable> C showStage(Class<C> controllerClass) throws IOException {
    FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlMap.get(controllerClass)));
    Parent parent = loader.load();
    Stage stage = new Stage();
    stage.setScene(new Scene(parent));
    stage.show();
    return loader.getController();
  }
}


画面Aから画面Bへの遷移処理(検索ボタンのアクション)

public class AController implements Initializable {
  @FXML
  private TextField filterText;

  @Override
  public void initialize(URL location, ResourceBundle resources) {

  }

  @FXML
  private void onShowB(ActionEvent ev) throws IOException {
    Stage stage = (Stage)((Node)ev.getSource()).getScene().getWindow();
    stage.hide();
    BController bController = MyApp.getInstance().showStage(BController.class);
    bController.setFilterText(filterText.getText());
  }
}


画面Bにて検索条件を受け取るメソッド

public class BController implements Initializable {
  @FXML
  TableView<Model> tableView;

  @Override
  public void initialize(URL location, ResourceBundle resources) {
    ...
  }

  public void setFilterText(String text) {
    // 指定テキストによりモデルを生成する(DBアクセスしてモデルインスタンスのリストを生成)
    // 時間がかかる処理ならバックグラウンドスレッドで行うべきだが、ここでは簡単のため
    // アプリケーションスレッドでやると想定
    List<Model> modelList = ...;
    tableView.getItems().setAll(modelList);
  }
}


自分が考えた点は以下です。

  • 多数の画面があるなら遷移処理を共通化したい
    アプリケーションクラスでshowStageというメソッドを用意し各画面ではこれを使う想定としました。また本質問の目的にあるように画面間での情報の引き渡しを遷移元と遷移先のコントローラーインスタンス間で行えるよう、画面遷移メソッドは遷移先のコントローラーを返すようにしています。
  • ステージのshowとコントローラークラスへの情報のやりとり順序
    例を簡単にするため共通メソッド(showStage)は無条件に生成したstageをshowし、その後にstageに結び付いたコントローラーインスタンスに対して情報設定メソッドを呼び出すと想定しています。viewがいかなる状態であろうと(表示前であろうと表示後であろうと)コントローラーやモデルの状態を変更した際にビューが適切に追従するように作ることは難しくないのですが、モデルの生成に時間がかかるような場合、画面を表示後にしばらくして表示内容が変わるのか、表示内容を確定させてから画面を表示させるかで見栄えが変わると思います。そうした点は細かなチューニング対象だと思います。
  • staticの仕様は最小限にする(追記2)
    本例ではアプリケーションインスタンスをシングルトンとしてMyApp#app及びMyApp#getInstanceのみstaticにしています。こうしておくと(殆どの定義がインスタンスフィールド、インスタンスメソッドのため)アプリケーションインスタンスを複数生成するような設計に変更する場合でも変更の影響を最小限にできると思います。Javaに限らずstatic(=グローバル)はできるだけ避けるという考え方があると思いますのでそれに倣ったつもりです。そういう想定が必要ないならこうした点をいちいち気にせず適宜staticにしてもよいとは思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/06 18:22

    回答の最後の方に「staticをなるべく避ける」ことについて追記しました。

    キャンセル

  • 2018/02/07 16:46

    様々な回答ありがとうございます。ここ最近調べながら頑張って理解しているところです。
    申し訳ないのですが、BControllerの 'List<Model> modelList = ...;' とはいったい何なのでしょうか?度々すみません。

    キャンセル

  • 2018/02/07 17:05

    それはTableViewへ表示すべきモデル群(Modelのリスト)を求めると想定して書いたものです。
    本件ですと引数に渡された検索条件に従ってDBアクセスし、結果セットの各行をModelクラスのインスタンスへと変換しそれをListとして蓄積するイメージです。TableViewは「なんらかのモデルクラスのインスタンス」を各行として表示しますよね?DBアクセスした結果の行をモデルクラスのインスタンスと見做すのはそういう意味合いです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる