【问题标题】:Open External Application From JavaFX从 JavaFX 打开外部应用程序
【发布时间】:2017-02-15 08:36:38
【问题描述】:

我找到了一种使用 HostServices 在默认浏览器上打开链接的方法。

getHostServices().showDocument("http://www.google.com");
  • 有没有办法在默认媒体播放器中打开媒体?
  • 有什么方法可以启动特定的文件应用程序

【问题讨论】:

  • 每当我尝试使用映射到特定文档的 URL(包括 file:// URL)时,它都会使用该文档类型的默认应用程序打开该文档。它对媒体等的工作方式不同吗?如果可以合理地这样做,最好避免混合 AWT 和 JavaFX(公认的答案就是这样)。
  • 是的,如果它包含file://,我将面对IllegalArgumentException。在阅读您的评论之前我没有注意到这是来自 AWT。如果您能分享您的答案,我将非常感谢您如何使用 JavaFX 做到这一点,这也将丰富我的知识和经验。
  • 好吧,我刚刚再次测试,它适用于 file:// URL,但不适用于具有 http: URL 的其他文档类型(它打开浏览器,下载文件)。我会添加一个答案,但是如果您想打开从网络服务器下载的媒体,我不确定是否有办法做到这一点。
  • 好的,不会有问题的。

标签: java javafx-8 external-application


【解决方案1】:

一般来说,你可以使用Desktop#open(file)原生打开文件,如下:

final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.OPEN)) {
    desktop.open(file);
} else {
    throw new UnsupportedOperationException("Open action not supported");
}

启动关联应用程序以打开文件。如果指定 file是一个目录,当前平台的文件管理器是 启动以打开它。

更具体地说,如果是浏览器,您可以直接使用Desktop#browse(uri),如下:

final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
    desktop.browse(uri);
} else {
    throw new UnsupportedOperationException("Browse action not supported");
}

启动默认浏览器以显示URI。如果默认浏览器 无法处理指定的URI,应用程序已注册 用于处理指定类型的URIs 被调用。该应用程序是 由URI 的协议和路径确定,由 URI 班级。如果调用线程没有必要的 权限,这是从小程序中调用的, 使用AppletContext.showDocument()。同样,如果调用 没有必要的权限,这是从内部调用的 Java Web Started 应用程序,使用BasicService.showDocument()

【讨论】:

  • 非常感谢。这个答案完全满足我的所有要求:)
【解决方案2】:

如果您想在浏览器中打开具有http: 方案的 URL,或者使用该文件类型的默认应用程序打开文件,您引用的 HostServices.showDocument(...) 方法提供了一种“纯 JavaFX”方式做这个。请注意,您不能使用它(据我所知)从 Web 服务器下载文件并使用默认应用程序打开它。

要使用默认应用程序打开文件,您必须将文件转换为file: URL 的字符串表示形式。这是一个简单的例子:

import java.io.File;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class OpenResourceNatively extends Application {

    @Override
    public void start(Stage primaryStage) {
        TextField textField = new TextField("http://stackoverflow.com/questions/39898704");
        Button openURLButton = new Button("Open URL");
        EventHandler<ActionEvent> handler = e -> open(textField.getText());
        textField.setOnAction(handler);
        openURLButton.setOnAction(handler);

        FileChooser fileChooser = new FileChooser();
        Button openFileButton = new Button("Open File...");
        openFileButton.setOnAction(e -> {
            File file = fileChooser.showOpenDialog(primaryStage);
            if (file != null) {
                open(file.toURI().toString());
            }
        });

        VBox root = new VBox(5, 
                new HBox(new Label("URL:"), textField, openURLButton),
                new HBox(openFileButton)
        );

        root.setPadding(new Insets(20));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private void open(String resource) {
        getHostServices().showDocument(resource);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

【讨论】:

  • 好的,现在我明白了。 HostServices.showDocument(...) 方法不仅可以只打开浏览器,还可以打开任何安装了操作系统默认应用程序的文件。非常感谢:)
  • 在 AWT 中有一种方法可以在 System Explorer 中打开目录。在 JavaFX 中如何在系统资源管理器中打开目录?
  • @RanaDepto 同样的事情,不是吗?如果file 指向一个目录,getHostServices().showDocument(file.toURI().toString()) 将在系统文件浏览器中打开该目录。
  • 是的,你是对的。看来我的大脑已经挂了。我应该自己意识到这一点。
  • 在 Ubuntu 17.10 amd64 上使用 OpenJFX 8u141,调用 HostServices#showDocument(String uri) 导致抛出以下异常:java.lang.ClassNotFoundException: com.sun.deploy.uitoolkit.impl.fx.HostServicesFactory
【解决方案3】:

只有java.awt.Desktop 的解决方案才能让我从 JavaFX 打开文件。

但是,起初,我的应用程序卡住了,我不得不弄清楚有必要从新线程调用Desktop#open(File file)。从当前线程或 JavaFX 应用程序线程 Platform#runLater(Runnable runnable) 调用该方法会导致应用程序无限期挂起,而不会引发异常。

这是一个带有工作文件打开解决方案的小型 JavaFX 应用程序示例:

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class FileOpenDemo extends Application {

    @Override
    public void start(Stage primaryStage) {
        final Button button = new Button("Open file");

        button.setOnAction(event -> {
            final FileChooser fileChooser = new FileChooser();
            final File file = fileChooser.showOpenDialog(primaryStage.getOwner());

            if (file == null)
                return;

            System.out.println("File selected: " + file.getName());

            if (!Desktop.isDesktopSupported()) {
                System.out.println("Desktop not supported");
                return;
            }

            if (!Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
                System.out.println("File opening not supported");
                return;
            }

            final Task<Void> task = new Task<Void>() {
                @Override
                public Void call() throws Exception {
                    try {
                        Desktop.getDesktop().open(file);
                    } catch (IOException e) {
                        System.err.println(e.toString());
                    }
                    return null;
                }
            };

            final Thread thread = new Thread(task);
            thread.setDaemon(true);
            thread.start();
        });

        primaryStage.setScene(new Scene(button));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

javafx.application.HostServices 提出的另一个解决方案根本不起作用。我在 Ubuntu 17.10 amd64 上使用 OpenJFX 8u141,调用 HostServices#showDocument(String uri) 时出现以下异常:

java.lang.ClassNotFoundException: com.sun.deploy.uitoolkit.impl.fx.HostServicesFactory

显然,JavaFX HostServices 尚未在所有平台上正确实现。关于这个主题另见:https://github.com/Qabel/qabel-desktop/issues/420

【讨论】:

  • 工作解决方案有很好的解释,我已经坚持了几天......谢谢
猜你喜欢
  • 2015-11-26
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多