2016-10-06 175 views
1

我找到了一種使用HostServices在默認瀏覽器上打開鏈接的方法。從JavaFX打開外部應用程序

getHostServices().showDocument("http://www.google.com"); 
  • 有什麼辦法來打開默認媒體播放媒體?
  • 有什麼辦法可以啓動特定的文件應用
+1

每當我嘗試使用映射到特定文檔的URL(包括文件:// URL)時,它會使用該文檔類型的默認應用程序打開文檔。它不適用於媒體等方式嗎?如果可以合理地這樣做,最好避免混合AWT和JavaFX(接受的答案)。 –

+0

是的,如果它包含'file://'我面臨'IllegalArgumentException'。在閱讀您的評論之前,我沒有注意到這是來自AWT。我非常感謝您分享您的答案,我如何使用JavaFX做到這一點,這將豐富我的知識和經驗。 –

+0

好吧,我只是再次測試,它與file:// URLs一起工作,但不能與其他帶有http:URL的文檔類型一起工作(它會打開瀏覽器,下載文件)。我會添加一個答案,但如果您想打開從Web服務器下載的媒體,我不確定是否有辦法做到這一點。 –

回答

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

好的,現在我明白了。 'HostServices.showDocument(...)'方法不僅可以打開瀏覽器,而且可以打開任何類型的文件,操作系統安裝了默認應用程序。非常感謝:) –

+0

在AWT中有一種方法可以在System Explorer中打開目錄。在JavaFX中如何在System Explorer中打開一個目錄? –

+0

@RanaDepto同樣的東西起作用,不是嗎?如果'file'指向一個目錄,'getHostServices()。showDocument(file.toURI()。toString())'將在系統文件瀏覽器中打開該目錄。 –

4

一般來說,你可以使用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"); 
} 

啓動相關應用打開該文件。如果指定的 文件是一個目錄,則啓動當前平臺的文件管理器 以打開它。

更具體地說,在瀏覽器的情況下,你可以直接使用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()

+1

非常感謝。這個答案完全符合我的所有要求:) –

0

只有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

相關問題