2014-04-19 74 views
16

我使用Oracle JDK 1.8.0_05通過NetBeans8.0在Ubuntu 12.04 LTS 64位(使用Gnome Shell)上運行Java中的一些代碼。JavaFX Freeze on Desktop.open(file),Desktop.browse(uri)

以下函數在Main或其他空的Java項目中調用時可以完美地工作,但是當從任何JavaFX應用程序調用時,它會導致窗口凍結並停止響應(儘管項目完全符合),要求它被迫關閉。

任何人都可以提出任何問題與我寫了哪些可能導致問題或循環?

唉,由於失敗的模式,我沒有可以提供或分析的錯誤消息。

任何建議感激地收到,在此先感謝。

public static void desktopTest(){ 

      Desktop de = Desktop.getDesktop(); 

      try { 
       de.browse(new URI("http://stackoverflow.com")); 
      } 
      catch (IOException | URISyntaxException e) { 
       System.out.println(e); 
      } 

      try { 
       de.open(new File("/home/aaa/file.ext")); 
      } 
      catch (IOException e){ 
       System.out.println(e); 
      } 
      try { 
       de.mail(new URI("mailto:[email protected]")); 
      } 
      catch (URISyntaxException | IOException e){ 
       System.out.println(e); 
      } 
} 

回答

21

我也有同樣的問題,該解決方案適用於我:

if(Desktop.isDesktopSupported()) 
{ 
    new Thread(() -> { 
      try { 
       Desktop.getDesktop().browse(new URI("http://...")); 
      } catch (IOException | URISyntaxException e1) { 
       e1.printStackTrace(); 
      } 
     }).start(); 
} 
+0

這裏的重要部分是'Desktop.isDesktopSupported()'。似乎會發生某種初始化。沒有它,它不起作用。這個答案應該被標記爲被接受的答案。 –

+2

是什麼使它對我的工作是創建一個新的線程 - 這似乎是必要的。 –

+0

看起來「Desktop.open()」具有相同的問題和解決方案。謝謝,亞歷克斯:)。 – jamie

2

我也有同樣的問題。我發現如果我從一個新線程調用Desktop.open()方法,該文件將在後打開我關閉了JavaFX應用程序窗口,但這並沒有多大幫助。

如果你把

SwingUtilities.invokeLater(() -> System.out.println("Hello world")); 
到您的主要方法

您推出後(參數)調用,它也不會被調用,直到關閉JavaFX應用程序之後。

似乎JavaFX應用程序和Swing之間存在某種併發問題。

在Ubuntu您可以從您的JavaFX應用程序嘗試

xdg-open filename 

據我所知,你的代碼應該是的工作。

+0

謝謝你,很高興知道我不會生氣 - 我知道w關於xdg-open,它工作正常,但我只使用Java來保證簡單的跨平臺可操作性......但是現在它的表面已經很平坦了 - 我可以問你正在運行的是什麼環境嗎?謝謝! – Wren

1

在JavaFX中有一種新的處理方法。我看到的唯一缺點是你需要使用Application singleton實例化一個HostServicesDelegate

HostServicesDelegate hostServices = HostServicesFactory.getInstance(appInstance); 
hostServices.showDocument("http://www.google.com"); 
+3

使用'com.sun' APIs,如'com.sun.deploy.uitoolkit.impl.fx.HostServicesFactory'是不明智的,因爲它們不能保證在未來的JavaFX版本中可用。而是使用public ['Application :: getHostServices()'](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Application.html#getHostServices--)API。 – jewelsea

3

我解決了問題...

public static void abrirArquivo(File arquivo) { 
    if (arquivo != null) { 
     if (arquivo.exists()) { 
      OpenFile openFile = new OpenFile(arquivo); 
      Thread threadOpenFile = new Thread(openFile); 
      threadOpenFile.start(); 
     } 
    } 
} 

private static class OpenFile implements Runnable { 

    private File arquivo; 

    public OpenFile(File arquivo) { 
     this.arquivo = arquivo; 
    } 

    private void abrirArquivo(File arquivo) throws IOException { 

     if (arquivo != null) { 
      java.awt.Desktop.getDesktop().open(arquivo); 
     } 

    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     try { 
      abrirArquivo(arquivo); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

} 
1

封裝它的系統上線:

final String url = "www.google.com"; 
    final Hyperlink hyperlink = new Hyperlink("Click me"); 
     hyperlink.setOnAction(event -> new Thread(() -> { 
      try { 
       Desktop.getDesktop().browse(new URI(url)); 
      } catch (IOException | URISyntaxException e1) { 
       e1.printStackTrace(); 
      } 
     }).start()); 
+0

你能提供額外的解釋嗎?是什麼導致了問題?爲什麼這個解決方案有效? –

+0

我確定JavaFX線程被'Destktop.getDesktop()。browse()'阻塞,但我不知道原因。 JavaFX線程只能用於與視圖相關的短任務(啓用/禁用按鈕,添加元素到列表,更改選項卡)。將_browse_命令封裝到系統線程中將允許JavaFX線程繼續刷新App視圖,而另一個線程可以在不中斷GUI的情況下自由打開瀏覽器。 (對不起,對於最近的答案) –