从 JavaFX 打开外部应用程序
Open External Application From JavaFX
我找到了一种使用 HostServices 在默认浏览器上打开 link 的方法。
getHostServices().showDocument("http://www.google.com");
- 有什么方法可以在默认媒体播放器中打开媒体吗?
- 有什么方法可以启动特定的 File 或 Application?
一般来说,您可以使用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");
}
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.
更具体地说,如果是浏览器,您可以直接使用 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");
}
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.
如果您想在浏览器中打开具有 http:
方案的 URL,或者使用该文件类型的默认应用程序打开文件,HostServices.showDocument(...)
方法您引用的提供了一种 "pure 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("");
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);
}
}
只有 java.awt.Desktop
的解决方案对我来说可以从 JavaFX 打开文件。
但是,起初,我的应用程序卡住了,我不得不弄清楚有必要调用 Desktop#open(File file)
from a new thread. Calling the method from the current thread or the JavaFX application thread 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
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
显然,JavaFX HostServices 尚未在所有平台上正确实施。关于此主题,另请参阅:https://github.com/Qabel/qabel-desktop/issues/420
我找到了一种使用 HostServices 在默认浏览器上打开 link 的方法。
getHostServices().showDocument("http://www.google.com");
- 有什么方法可以在默认媒体播放器中打开媒体吗?
- 有什么方法可以启动特定的 File 或 Application?
一般来说,您可以使用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");
}
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.
更具体地说,如果是浏览器,您可以直接使用 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");
}
Launches the default browser to display a
URI
. If the default browser is not able to handle the specifiedURI
, the application registered for handlingURIs
of the specified type is invoked. The application is determined from the protocol and path of theURI
, as defined by theURI
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.
如果您想在浏览器中打开具有 http:
方案的 URL,或者使用该文件类型的默认应用程序打开文件,HostServices.showDocument(...)
方法您引用的提供了一种 "pure 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("");
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);
}
}
只有 java.awt.Desktop
的解决方案对我来说可以从 JavaFX 打开文件。
但是,起初,我的应用程序卡住了,我不得不弄清楚有必要调用 Desktop#open(File file)
from a new thread. Calling the method from the current thread or the JavaFX application thread 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
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
显然,JavaFX HostServices 尚未在所有平台上正确实施。关于此主题,另请参阅:https://github.com/Qabel/qabel-desktop/issues/420