Open External Application From JavaFX

这一生的挚爱 提交于 2019-12-13 14:08:15

问题


I found a way to open a link on default browser using HostServices.

getHostServices().showDocument("http://www.google.com");
  • Is there any way to open a media in default media player?
  • Is there any way to launch a specific File or Application?

回答1:


If you want to either open a URL which has an http: scheme in the browser, or open a file using the default application for that file type, the HostServices.showDocument(...) method you referenced provides a "pure JavaFX" way to do this. Note that you can't use this (as far as I can tell) to download a file from a web server and open it with the default application.

To open a file with the default application, you must convert the file to the string representation of the file: URL. Here is a simple example:

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



回答2:


Generally speaking, you can use Desktop#open(file) to open a file natively as next:

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

Launches the associated application to open the file. If the specified file is a directory, the file manager of the current platform is launched to open it.

More specifically, in case of a browser you can use directly Desktop#browse(uri), as next:

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

Launches the default browser to display a URI. If the default browser is not able to handle the specified URI, the application registered for handling URIs of the specified type is invoked. The application is determined from the protocol and path of the URI, as defined by the URI class. If the calling thread does not have the necessary permissions, and this is invoked from within an applet, AppletContext.showDocument() is used. Similarly, if the calling does not have the necessary permissions, and this is invoked from within a Java Web Started application, BasicService.showDocument() is used.




回答3:


Only the solution with java.awt.Desktop worked for me to open a file from JavaFX.

However, at first, my application got stuck and I had to figure out that it is necessary to call Desktop#open(File file) from a new thread. Calling the method from the current thread or the JavaFX application thread Platform#runLater(Runnable runnable) resulted in the application to hang indefinitely without an exception being thrown.

This is a small sample JavaFX application with the working file open solution:

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

The other proposed solution with javafx.application.HostServices did not work at all. I am using OpenJFX 8u141 on Ubuntu 17.10 amd64 and I got the following exception when invoking HostServices#showDocument(String uri):

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

Obviously, JavaFX HostServices is not yet properly implemented on all platforms. On this topic see also: https://github.com/Qabel/qabel-desktop/issues/420



来源:https://stackoverflow.com/questions/39898704/open-external-application-from-javafx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!