前提・実現したいこと
何度も質問すみません。
実現したい内容は下の画像になります。
今作成しているプログラムは画面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 ![![イメージ説明](cf4599d01de9b633655ac33d64dd48ee.png)](31b9b64b02af9b1ad8267c825446577f.png)
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
ベストアンサー
ユーザーとの対話をするための小さな画面を一般にダイアログと呼びます。多分画面Aはダイアログとして設計できると思います。
ダイアログを実装するためには通常の画面(JavaFXではStage)と同様にもできます。質問者さんはおそらくそういうイメージをお持ちであろうと思います。しかしながら大抵のGUIライブラリーと同様JavaFXもダイアログを簡便に実装するための特化機能が用意されておりそちらを使う方がより簡単と思います。
JavaFXでのダイアログはjavafx.scene.control.Dialogというベースクラスおよびその派生として定義することが想定されていますが、本件のように文字列テキストの入力なら専用クラスjavafx.scene.control.TextInputDailogが用意されていますのでそれを使うのがよいと思います。
簡単な例を挙げてみますと以下のようになります。
java
1TextInputDialog dialog = new TextInputDialog("") { 2 { 3 setTitle("filtering"); 4 setHeaderText("input filtering text"); 5 } 6}; 7Optional<String> optInput = dialog.showAndWait(); 8if (!optInput.isPresent()) { 9 // キャンセルが押された場合optInputは値を持たない 10 System.out.println("cancelled"); 11} else { 12 // OKが押された場合はoptInputは値を持ち、それはgetにより得られる。 13 System.out.println("input text = " + optInput.get()); 14}
上記ではデフォルトから2点のみ動作を変えています。一つはダイアログタイトルで、もう一つはヘッダーテキストです。様々なカスタマイズをするためにはjavafx.control.Dialogの機能を調べるとやり方がわかってきますが、とりあえずはデフォルトの振る舞いがどのようになっているかを観察してみるとよいでしょう。
他のコントローラクラスにその入力された値を渡す方法が分からず悩んでいます。
ダイアログを用いる場合、ユーザーの入力結果はshowAndWaitメソッドの戻り値になるので、それを用いることになります。本件の場合、画面Bのコントローラーインスタンスへなんらかの方法で渡すのが自然と思います。渡し方は画面Bをどうやって生成・表示するかによって若干のバリエーションがありますが、FXMLとFXMLLoaderにより画面を生成する方法を用いるなら、以下のようにFXMLロード後にコントローラーインスタンスを取得しそこに定義したメソッドを通じて設定という流れが典型的な方法の一つだと思います。
java
1FXMLLoader loader = new FXMLLoader(...); 2loader.load(); 3ControllerB controllerB = loader.getController(); 4controllerB.setFilterText(optInput.get());
追記:
回答コメントから質問者さんの想定がダイアログではないようですので、各画面のStage, コントローラーを画面遷移の都度生成する前提に注意しつつ、画面遷移方法を考えてみました。以下の例は唯一の方法でもベストなものというわけではありません。やりかたには微妙なバリエーションがあるでしょう。つまり「ある画面から別の画面へ情報を引き渡す」実装例の一つです。
画面遷移メソッド(アプリケーションクラスに用意する例)
java
1public class MyApp extends Application { 2 private static MyApp app; 3 4 public static MyApp getInstance() { 5 return Objects.requireNonNull(app); 6 } 7 8 public MyApp() { app = this; } 9 10 HashMap<Class<? extends Initializable>, String> fxmlMap = new HashMap<>(); 11 12 @Override 13 public void start(Stage stage) { 14 fxmlMap.put(AController.class, "A.fxml"); 15 fxmlMap.put(BController.class, "B.fxml"); 16 17 try { 18 Parent root = FXMLLoader.load(getClass().getResource("Main.fxml")); 19 stage.setScene(new Scene(root)); 20 stage.show(); 21 } catch (IOException e) { 22 throw new UncheckedIOException(e); 23 } 24 } 25 26 public <C extends Initializable> C showStage(Class<C> controllerClass) throws IOException { 27 FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlMap.get(controllerClass))); 28 Parent parent = loader.load(); 29 Stage stage = new Stage(); 30 stage.setScene(new Scene(parent)); 31 stage.show(); 32 return loader.getController(); 33 } 34}
画面Aから画面Bへの遷移処理(検索ボタンのアクション)
java
1public class AController implements Initializable { 2 @FXML 3 private TextField filterText; 4 5 @Override 6 public void initialize(URL location, ResourceBundle resources) { 7 8 } 9 10 @FXML 11 private void onShowB(ActionEvent ev) throws IOException { 12 Stage stage = (Stage)((Node)ev.getSource()).getScene().getWindow(); 13 stage.hide(); 14 BController bController = MyApp.getInstance().showStage(BController.class); 15 bController.setFilterText(filterText.getText()); 16 } 17}
画面Bにて検索条件を受け取るメソッド
java
1public class BController implements Initializable { 2 @FXML 3 TableView<Model> tableView; 4 5 @Override 6 public void initialize(URL location, ResourceBundle resources) { 7 ... 8 } 9 10 public void setFilterText(String text) { 11 // 指定テキストによりモデルを生成する(DBアクセスしてモデルインスタンスのリストを生成) 12 // 時間がかかる処理ならバックグラウンドスレッドで行うべきだが、ここでは簡単のため 13 // アプリケーションスレッドでやると想定 14 List<Model> modelList = ...; 15 tableView.getItems().setAll(modelList); 16 } 17}
自分が考えた点は以下です。
- 多数の画面があるなら遷移処理を共通化したい
アプリケーションクラスでshowStageというメソッドを用意し各画面ではこれを使う想定としました。また本質問の目的にあるように画面間での情報の引き渡しを遷移元と遷移先のコントローラーインスタンス間で行えるよう、画面遷移メソッドは遷移先のコントローラーを返すようにしています。
- ステージのshowとコントローラークラスへの情報のやりとり順序
例を簡単にするため共通メソッド(showStage)は無条件に生成したstageをshowし、その後にstageに結び付いたコントローラーインスタンスに対して情報設定メソッドを呼び出すと想定しています。viewがいかなる状態であろうと(表示前であろうと表示後であろうと)コントローラーやモデルの状態を変更した際にビューが適切に追従するように作ることは難しくないのですが、モデルの生成に時間がかかるような場合、画面を表示後にしばらくして表示内容が変わるのか、表示内容を確定させてから画面を表示させるかで見栄えが変わると思います。そうした点は細かなチューニング対象だと思います。
- staticの仕様は最小限にする(追記2)
本例ではアプリケーションインスタンスをシングルトンとしてMyApp#app及びMyApp#getInstanceのみstaticにしています。こうしておくと(殆どの定義がインスタンスフィールド、インスタンスメソッドのため)アプリケーションインスタンスを複数生成するような設計に変更する場合でも変更の影響を最小限にできると思います。Javaに限らずstatic(=グローバル)はできるだけ避けるという考え方があると思いますのでそれに倣ったつもりです。そういう想定が必要ないならこうした点をいちいち気にせず適宜staticにしてもよいとは思います。
投稿2018/02/05 05:05
編集2018/02/06 09:21総合スコア18394
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/02/06 01:45
2018/02/06 01:56
2018/02/06 02:54
2018/02/06 03:03
2018/02/06 03:24
2018/02/06 03:29
2018/02/06 05:44
2018/02/06 09:22
2018/02/07 07:46
2018/02/07 08:05