teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

追記

2018/02/06 09:21

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

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

1

追記

2018/02/06 09:21

投稿

KSwordOfHaste
KSwordOfHaste

スコア18404

answer CHANGED
@@ -34,4 +34,91 @@
34
34
  loader.load();
35
35
  ControllerB controllerB = loader.getController();
36
36
  controllerB.setFilterText(optInput.get());
37
- ```
37
+ ```
38
+
39
+ ---
40
+ 追記:
41
+ 回答コメントから質問者さんの想定がダイアログではないようですので、各画面のStage, コントローラーを画面遷移の都度生成する前提に注意しつつ、画面遷移方法を考えてみました。以下の例は唯一の方法でもベストなものというわけではありません。やりかたには微妙なバリエーションがあるでしょう。つまり「ある画面から別の画面へ情報を引き渡す」実装例の一つです。
42
+
43
+ 画面遷移メソッド(アプリケーションクラスに用意する例)
44
+ ```java
45
+ public class MyApp extends Application {
46
+ private static MyApp app;
47
+
48
+ public static MyApp getInstance() {
49
+ return Objects.requireNonNull(app);
50
+ }
51
+
52
+ public MyApp() { app = this; }
53
+
54
+ HashMap<Class<? extends Initializable>, String> fxmlMap = new HashMap<>();
55
+
56
+ @Override
57
+ public void start(Stage stage) {
58
+ fxmlMap.put(AController.class, "A.fxml");
59
+ fxmlMap.put(BController.class, "B.fxml");
60
+
61
+ try {
62
+ Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
63
+ stage.setScene(new Scene(root));
64
+ stage.show();
65
+ } catch (IOException e) {
66
+ throw new UncheckedIOException(e);
67
+ }
68
+ }
69
+
70
+ public <C extends Initializable> C showStage(Class<C> controllerClass) throws IOException {
71
+ FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlMap.get(controllerClass)));
72
+ Parent parent = loader.load();
73
+ Stage stage = new Stage();
74
+ stage.setScene(new Scene(parent));
75
+ stage.show();
76
+ return loader.getController();
77
+ }
78
+ }
79
+ ```
80
+ 画面Aから画面Bへの遷移処理(検索ボタンのアクション)
81
+ ```java
82
+ public class AController implements Initializable {
83
+ @FXML
84
+ private TextField filterText;
85
+
86
+ @Override
87
+ public void initialize(URL location, ResourceBundle resources) {
88
+
89
+ }
90
+
91
+ @FXML
92
+ private void onShowB(ActionEvent ev) throws IOException {
93
+ Stage stage = (Stage)((Node)ev.getSource()).getScene().getWindow();
94
+ stage.hide();
95
+ BController bController = MyApp.getInstance().showStage(BController.class);
96
+ bController.setFilterText(filterText.getText());
97
+ }
98
+ }
99
+ ```
100
+ 画面Bにて検索条件を受け取るメソッド
101
+ ```java
102
+ public class BController implements Initializable {
103
+ @FXML
104
+ TableView<Model> tableView;
105
+
106
+ @Override
107
+ public void initialize(URL location, ResourceBundle resources) {
108
+ ...
109
+ }
110
+
111
+ public void setFilterText(String text) {
112
+ // 指定テキストによりモデルを生成する(DBアクセスしてモデルインスタンスのリストを生成)
113
+ // 時間がかかる処理ならバックグラウンドスレッドで行うべきだが、ここでは簡単のため
114
+ // アプリケーションスレッドでやると想定
115
+ List<Model> modelList = ...;
116
+ tableView.getItems().setAll(modelList);
117
+ }
118
+ }
119
+ ```
120
+ 自分が考えた点は以下です。
121
+ - 多数の画面があるなら遷移処理を共通化したい
122
+ アプリケーションクラスでshowStageというメソッドを用意し各画面ではこれを使う想定としました。また本質問の目的にあるように画面間での情報の引き渡しを遷移元と遷移先のコントローラーインスタンス間で行えるよう、画面遷移メソッドは遷移先のコントローラーを返すようにしています。
123
+ - ステージのshowとコントローラークラスへの情報のやりとり順序
124
+ 例を簡単にするため共通メソッド(showStage)は無条件に生成したstageをshowし、その後にstageに結び付いたコントローラーインスタンスに対して情報設定メソッドを呼び出すと想定しています。viewがいかなる状態であろうと(表示前であろうと表示後であろうと)コントローラーやモデルの状態を変更した際にビューが適切に追従するように作ることは難しくないのですが、モデルの生成に時間がかかるような場合、画面を表示後にしばらくして表示内容が変わるのか、表示内容を確定させてから画面を表示させるかで見栄えが変わると思います。そうした点は細かなチューニング対象だと思います。