解決策1:HostServices
への参照をアプリケーションに渡します。
これはおそらく、あなたが予想している「かなり痛い」アプローチに似ています。 MainController
で、その後
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
Parent root = loader.load();
MainController controller = loader.getController();
controller.setHostServices(getHostServices());
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
と::
public class DialogController {
@FXML
private Hyperlink hyperlink ;
private HostServices hostServices ;
public HostServices getHostServices() {
return hostServices ;
}
public void setHostServices(HostServices hostServices) {
this.hostServices = hostServices ;
}
@FXML
private void openURL() {
hostServices.openDocument(hyperlink.getText());
}
}
解決方法2:
public class MainController { private HostServices hostServices ; public HostServices getHostServices() { return hostServices ; } public void setHostServices(HostServices hostServices) { this.hostServices = hostServices ; } @FXML private void showDialog() { FXMLLoader loader = new FXMLLoader(getClass().getResource("dialog.fxml")); Parent dialogRoot = loader.load(); DialogController dialogController = loader.getController(); dialogController.setHostServices(hostServices); Stage dialog = new Stage(); dialog.setScene(new Scene(dialogRoot)); dialog.show(); } }
そしてもちろんDialogController
の
がどのように見える使用しますが、基本的に、あなたのような何かをするだろうホストサービスをプッシュするコントローラファクトリコントローラに接続します。
これは、上記のよりクリーンなバージョンです。今
public class HostServicesControllerFactory implements Callback<Class<?>,Object> {
private final HostServices hostServices ;
public HostServicesControllerFactory(HostServices hostServices) {
this.hostServices = hostServices ;
}
@Override
public Object call(Class<?> type) {
try {
for (Constructor<?> c : type.getConstructors()) {
if (c.getParameterCount() == 1 && c.getParameterTypes()[0] == HostServices.class) {
return c.newInstance(hostServices) ;
}
}
return type.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
:代わりのコントローラを取得し、それらを初期化するメソッドを呼び出すと、それは、適切なコンストラクタを持っている場合、あなたは、controllerFactory
経由でそれらの作成を設定し、コントローラのコンストラクタにHostServices
オブジェクトを渡すことでコントローラーを作成しますあなたはFXMLをロードする際、コントローラの工場を使用します。
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
loader.setControllerFactory(new HostServicesControllerFactory(getHostServices()));
Parent root = loader.load();
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
とコンストラクタのパラメータとしてHostServices
を取るために、あなたのコントローラを定義します:
public class MainController {
private final HostServices hostServices ;
public MainController(HostServices hostServices) {
this.hostServices = hostServices ;
}
@FXML
private void showDialog() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("dialog.fxml"));
loader.setControllerFactory(new HostServicesControllerFactory(hostServices));
Parent dialogRoot = loader.load();
Stage dialog = new Stage();
dialog.setScene(new Scene(dialogRoot));
dialog.show();
}
}
そしてもちろん
public class DialogController {
@FXML
private Hyperlink hyperlink ;
private final HostServices hostServices ;
public DialogController(HostServices hostServices) {
this.hostServices = hostServices ;
}
@FXML
private void openURL() {
hostServices.openDocument(hyperlink.getText());
}
}
解決策3:これは無残醜いソリューションです、と私は強く、それを使用しないことをお勧めします。私はそれを含めたいと思ったので、投稿したときに他の誰かを怒らせることなく表現することができました。静的フィールドにホストサービスを格納します。
public class MainApp extends Application {
private static HostServices hostServices ;
public static HostServices getHostServices() {
return hostServices ;
}
public void start(Stage primaryStage) throws Exception {
hostServices = getHostServices();
Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
次に、あなただけのあなたが必要
MainApp.getHostServices().showDocument(hyperlink.getText());
のどこを行います。ここでの問題の1つは、ホストサービスにアクセスする必要があるすべてのコントローラのアプリケーションタイプに依存することです。
ソリューション4シングルトンHostServicesProvider
を定義します。これは解決策3よりは優れていますが、それでもまだ良い解決策はありません。
public enum HostServicesProvider {
INSTANCE ;
private HostServices hostServices ;
public void init(HostServices hostServices) {
if (this.hostServices != null) {
throw new IllegalStateException("Host services already initialized");
}
this.hostServices = hostServices ;
}
public HostServices getHostServices() {
if (hostServices == null) {
throw new IllegalStateException("Host services not initialized");
}
return hostServices ;
}
}
は今、あなただけの依存性注入フレームワークを使用しソリューション5
public void start(Stage primaryStage) throws Exception {
HostServicesProvider.INSTANCE.init(getHostServices());
// just load and show main app...
}
と
public class DialogController {
@FXML
private Hyperlink hyperlink ;
@FXML
private void openURL() {
HostServicesProvider.INSTANCE.getHostServices().showDocument(hyperlink.getText());
}
}
を必要としています。おそらく現在のユースケースには当てはまりませんが、これらの(比較的シンプルな)フレームワークがどれほど強力であるかがわかります。
あなたがafterburner.fxを使用している場合たとえば、あなたは自分のアプリケーションstart()
やinit()
方法で
Injector.setModelOrService(HostServices.class, getHostServices());
を行う必要があり、その後、
public class DialogPresenter {
@Inject
private HostServices hostServices ;
@FXML
private Hyperlink hyperlink ;
@FXML
private void showURL() {
hostServices.showDocument(hyperlink.getText());
}
}
春を使用した例がhereです。
は醜い静的なソリューションが動作しません... getStage()と呼ばれる私のcontollerクラスのメソッドを持っていますgetStaticHostServices。私のユースケースでは最小の努力のソリューションです。 –
@WolfgangFahlええ、おそらく。とにかく、私が強くお勧めするものを試してみるかどうかは分かりません。 –
心配しない私は今、インターフェイスを使用しています public interface Linker { public void browse(String url); }実装を隠す - 静的なものはそのようには必要ありません –