簡體   English   中英

如何在Java 9+中使用JFileChooser顯示網絡共享?

[英]How to display network shares using JFileChooser in Java 9+?

我們軟件的用戶需要在我們的Java swing應用程序中瀏覽Windows 10上的網絡共享,但是swing的JFileChooser默認情況下不具備此功能。

在這篇相關文章中如何在JFileChooser中導航到網絡主機? 使用ShellFolder(sun私有API)來設置JFileChooser的當前目錄是一個不錯的解決方案,我們在過去幾年中一直使用這種方法進行一些修改而沒有任何問題。

public static File getNetworkShareFolder( final File folder ) throws IllegalArgumentException {
  final File file = new NonCanonicalizingFile( folder.getPath() );
  if( isNetworkShareFolder( file ) ) { // assume Win32ShellFolderManager2 will be present
     try {
        // JRE-13272 -PRIVATE API that must eventually be swapped for Java 9 alternative
        // Using reflection because Win32ShellFolderManager2 may not exist in rt.jar on Linux build server
        final Class win32ShellMgr = Class.forName( "sun.awt.shell.Win32ShellFolderManager2" );
        // get static creation method from class, execute it
        final Method cfMethod = win32ShellMgr.getMethod( "createShellFolder", File.class );
        return (ShellFolder) cfMethod.invoke( win32ShellMgr.newInstance(), file );
     } catch( final Exception xx ) {
        xx.printStackTrace();
     }
  }
  throw new IllegalArgumentException( "Given path is not a Windows network share folder." ); 
} 

但是,我們正在轉向Java 11,並且在Java 9中,私有API被封裝,我們已經被要求不再使用它們。 不用擔心,OpenJDK中的替換API已進入FileSystemView,在swing filechooser的子包中。

sun.awt.shell.ShellFolder.isComputerNode(File) - > javax.swing.filechooser.FileSystemView.getFileSystemView()。isComputerNode(File)sun.awt.shell.ShellFolder.getShellFolder(File) - > javax.swing.filechooser。 FileSystemView.getFileSystemView()。getLinkLocation(File)

所以現在的代碼變成了

public static File getNetworkShareFolder( final File folder ) throws IllegalArgumentException {
   final File file = new NonCanonicalizingFile( folder.getPath() );
   if( isNetworkShareFolder( file ) ) { 
      try {
         return FileSystemView.getFileSystemView().getLinkLocation( file );
      } catch( final Exception xx ) {
         xx.printStackTrace();
      }
   }
   throw new IllegalArgumentException( "Given path is not a Windows network share folder." );
}

public static boolean isNetworkShareFolder( final File folder ) {
   return FileSystemView.getFileSystemView().isComputerNode( new NonCanonicalizingFile( folder.getPath() ) );
}

這將是很好的,但不幸的是,兩個getShellFolder()和getLinkLocation()在Java 11下拋出了一個在Java 8下沒有拋出的異常。

java.nio.file.InvalidPathException:UNC路徑在java.base / sun.nio.fs上的java.base / sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:118)中缺少sharename:\\ 100.212.51.37。 WindowsPathParser.parse(WindowsPathParser.java:77)位於java.base / sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)java.base / sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java: 229)java.desktop / sun的java.base / java.nio.file.Path.of(Path.java:147)java.base / java.nio.file.Paths.get(Paths.java:69) .awt.shell.ShellFolder.getShellFolder(ShellFolder.java:247)at java.desktop / javax.swing.filechooser.FileSystemView.getLinkLocation(FileSystemView.java:641)

看來它現在認為UNC路徑無效,除非它有實際的共享名稱,即“\\\\ 100.212.51.37”無效,但“\\\\ 100.212.51.37 \\ myShare”沒問題。

現在,如果您獲得UNC路徑“\\\\ 100.212.51.37 \\ myShare”的shell文件夾,然后獲取getParent(),則首先獲得我們想要的“\\\\ 100.212.51.37 \\”的shell文件夾。 不幸的是,這種解決方法對於我們的客戶來說是不可行的,因為雞和雞蛋問題 - 用戶通常還不知道任何實際的共享名稱,這是他們想要首先瀏覽的內容!

Argh - 這在Java 8下運行良好,但在Java 11中,即使你打破封裝使用原來的ShellFolder私有API也是如此

 '--add-exports', 'java.desktop/sun.awt.shell=ALL-UNNAMED' 

它沒有用,因為之前的解決方案現在在Java 11(9+)下拋出相同的Exception。

我們已經看到在計算器上的另一個解決方案是使用SmbFile類JCIFS ,但由於安全限制是很難供我們使用第三方代碼。 特別是如果沒有使用私有API更新Java 11 JPMS。

有趣的是,JavaFX中的DirectoryChooser沒有這個問題。 如果用戶手動鍵入網絡主機,它將很樂意顯示該主機的所有共享名稱。 如果我們必須這樣做,我們將采用這種方式,但是在一個搖擺應用程序的FX階段之間處理模態是丑陋的,並且可能是非常多的工作。

仍然希望更簡單的解決方法讓JFileChooser在Java 11(Java 9+)中顯示網絡共享! 也許有人知道FX DirectoryChooser正在使用的技巧,它可以應用於JFileChooser?

仍在尋找更好的解決方案,但與此同時,由於網絡共享,我們決定用Java 11中的JavaFX的DirectoryChooser替換JFileChooser。 DirectoryChooser非常樂意允許用戶鍵入根網絡共享,它將顯示所有網絡共享名稱。 啟動DirectoryChooser的UI仍然是一個swing UI,但我們沒有遇到模態或焦點問題,至少在Windows 10下。

但是,除了必須仔細管理JavaFX Platform.runLater()和SwingUtilities.invokeLater()之間的線程之外,還有一些重大缺陷。

1)DirectoryChooser不允許多項選擇。 JFileChooser。

2)DirectoryChooser ONLY允許選擇目錄而不是文件。 Shrugs誰需要允許選擇目錄或文件? 愚蠢。 只有這就是我們的客戶需要在多個實例中完成的工作。 JFileChooser支持這一點。

3)DirectoryChooser不允許輸入無效路徑。 咦? 是的,事實上,我們的一個客戶有一個特定的要求,即輸入一個尚不存在的路徑(預先配置),但是一旦任務驅動器插入網絡就會有。 JFileChooser允許這樣做,並且可以非常方便地導航到您需要的根目錄,然后只需鍵入路徑的最后一部分(目錄或共享名稱)。

4)DirectoryChooser與應用程序樣式不匹配。 在JavaFX中,您可以在場景的根節點上設置自己的CSS,但不能在DirectoryChooser上設置。 看起來DirectoryChooser實際上正在調用本機文件選擇器,它應該使用系統顏色方案。 不幸的是,我們的飛行員在晚上使用“暗模式”操作,Windows 10文件資源管理器不會尊重“暗模式”設置,直到版本1809,幾乎沒有我們的客戶擁有。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM