栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JavaFx 8:在浏览器中打开链接而不引用应用程序

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaFx 8:在浏览器中打开链接而不引用应用程序

解决方案1:

HostServices
通过您的应用程序向下传递引用。

这可能类似于您预期的“非常痛苦”的方法。但基本上,您会执行以下操作:

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();}

然后在

MainController

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 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: 使用控制器工厂将主机服务推送到控制器。

这是上面的更干净的版本。您无需通过获取控制器并调用方法来对其进行初始化,而是通过a来配置它们的创建,并通过

controllerFactory
将一个
HostServices
对象传递给控制器的构造函数(如果它具有合适的构造函数)来创建控制器:

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);        }    }}

现在,在加载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());

您需要的任何地方。这里的问题之一是,您为需要访问主机服务的所有控制器引入了对应用程序类型的依赖。


解决方案4 定义一个单例

HostServicesProvider
。这比解决方案3更好,但仍然不是imo的好解决方案。

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 ;    }}

现在你只需要

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());    }}

解决方案5 使用依赖项注入框架。这可能不适用于您当前的用例,但可能会让您了解这些(相对简单的)框架的功能。

例如,如果您使用afterburner.fx,则只需执行以下操作

Injector.setModelOrService(HostServices.class, getHostServices());

在您的应用程序

start()
init()
方法中,然后

public class DialogPresenter {    @Inject    private HostServices hostServices ;    @FXML    private Hyperlink hyperlink ;    @FXML    private void showURL() {        hostServices.showdocument(hyperlink.getText());    }}

这里有一个使用Spring的例子。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/496845.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号