簡體   English   中英

Swing是否支持Windows 7樣式的文件選擇器?

[英]Does Swing support Windows 7-style file choosers?

我剛剛根據Swing教程JFileChooser條目在正在編寫的小型桌面應用程序中添加了一個標准的“ 打開文件 ”對話框。 它正在生成一個如下所示的窗口:

不需要的/ XP樣式的窗口的屏幕截圖

但我希望有一個看起來像這樣的窗口:

所需/ 7樣式窗口的屏幕截圖

換句話說,我希望文件選擇器具有Windows Vista / Windows 7的樣式,而不是Windows XP的樣式。 在Swing中有可能嗎? 如果是這樣,怎么做? (出於這個問題的目的,假定代碼將僅在Windows 7計算機上運行。)

似乎Java 6中的Swing不支持此功能。

當前,我找到打開此對話框的最簡單方法是通過SWT而不是Swing。 SWT的FileDialog( javadoc )彈出此對話框。 以下是對SWT的FileDialog代碼段的修改,以使用打開對話框而不是保存對話框。 我知道這並不是您想要的,但是您可以將其隔離到實用程序類,然后將swt.jar添加到您的類路徑中以實現此功能。

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;

public class SWTFileOpenSnippet {
    public static void main (String [] args) {
        Display display = new Display ();
        Shell shell = new Shell (display);
        // Don't show the shell.
        //shell.open ();  
        FileDialog dialog = new FileDialog (shell, SWT.OPEN | SWT.MULTI);
        String [] filterNames = new String [] {"All Files (*)"};
        String [] filterExtensions = new String [] {"*"};
        String filterPath = "c:\\";
        dialog.setFilterNames (filterNames);
        dialog.setFilterExtensions (filterExtensions);
        dialog.setFilterPath (filterPath);
        dialog.open();
        System.out.println ("Selected files: ");
        String[] selectedFileNames = dialog.getFileNames();
        for(String fileName : selectedFileNames) {
            System.out.println("  " + fileName);
        }
        shell.close();
        while (!shell.isDisposed ()) {
            if (!display.readAndDispatch ()) display.sleep ();
        }
        display.dispose ();
    }
} 

甚至本機Windows應用程序也可以在Windows 7上顯示這種類型的對話框。這通常由OPENFILENAME結構中的標志控制,其大小通過調用WinAPI函數GetOpenFileName傳遞。 Swing(Java)使用鈎子從“打開文件”對話框中獲取事件; 這些事件在Windows XP和Windows 7版本之間傳遞的方式有所不同。

因此,答案是您無法控制Swing中FileChooser的外觀。 但是,當Java獲得這種新外觀的支持時,您將自動獲得新樣式。

另一個選擇是使用SWT,如該答案中所建議。 另外,您可以使用JNA調用Windows API或編寫本機方法來執行此操作。

Java 8可能最終會為此提供解決方案,但不幸的是(對於Swing應用程序),它僅作為JavaFX類FileChooser出現

我從這里測試了此代碼,它的確彈出了一個現代對話框(此處為Windows 7):

FileChooser fileChooser = new FileChooser();

//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);

//Show open file dialog
File file = fileChooser.showOpenDialog(null);

這種集成到Swing應用程序,你必須在通過JavaFX的線程中運行它Platform.runLater (如看到這里 )。

請注意,這將需要您初始化javafx線程(在示例中,這是在場景初始化時在new JFXPanel() )。

綜上所述,swing應用程序中的准備運行的解決方案如下所示:

new JFXPanel(); // used for initializing javafx thread (ideally called once)
Platform.runLater(() -> {
    FileChooser fileChooser = new FileChooser();

    //Set extension filter
    FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
    FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
    fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);

    //Show open file dialog
    File file = fileChooser.showOpenDialog(null);
});

有點hack,但功能比Swing版本要少,但是您是否考慮過使用java.awt.FileDialog 它不僅看起來像Windows文件選擇器,而且實際上應該是一個。

我不相信Swing會涵蓋所有內容,如果沒有,您可能需要查看SWT之類的東西,它會利用實際的本機組件,或者做一個自定義UI元素,例如《骯臟的富客戶》一書。

很好的問題+1,看起來就像他們“忘記”在Java6中實現Win7(defaultLookAndFeel)的實現一樣,但是對於WinXP來說卻是正確的,我也希望為此必須存在一些方法/屬性

無論如何,您可以使用此代碼進行嘗試,

import java.io.File;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;

class ChooserFilterTest {

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                String[] properties = {"os.name", "java.version", "java.vm.version", "java.vendor"};
                for (String property : properties) {
                    System.out.println(property + ": " + System.getProperty(property));
                }
                JFileChooser jfc = new JFileChooser();
                jfc.showOpenDialog(null);
                jfc.addChoosableFileFilter(new FileFilter() {

                    @Override
                    public boolean accept(File f) {
                        return f.isDirectory() || f.getName().toLowerCase().endsWith(".obj");
                    }

                    @Override
                    public String getDescription() {
                        return "Wavefront OBJ (*.obj)";
                    }

                    @Override
                    public String toString() {
                        return getDescription();
                    }
                });
                int result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
                System.out.println("Displayed description (Metal): " + (result == JOptionPane.YES_OPTION));
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    SwingUtilities.updateComponentTreeUI(jfc);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                jfc.showOpenDialog(null);
                result = JOptionPane.showConfirmDialog(null, "Description was 'All Files'?");
                System.out.println("Displayed description (System): " + (result == JOptionPane.YES_OPTION));
            }
        };
        SwingUtilities.invokeLater(r);
    }

    private ChooserFilterTest() {
    }
}

但是無法使此工作適用於目錄!! DirectoryDialog使我們回到樹樣式目錄選擇器,該選擇器與問題中列出的選擇器相同。 問題是它不允許我選擇/選擇/打開隱藏文件夾。 它也不允許導航到AppData,ProgramData等文件夾。

Windows 7樣式文件對話框(swt)確實允許導航到這些文件夾,但隨后又不允許選擇文件夾:(

更新要查看隱藏的文件夾,請使用JFileChooser並設置setFileHidingEnabled(false) 唯一的要求是,用戶需要在工具欄中選擇“顯示隱藏的文件,文件夾和驅動器”

文件夾選項->查看

Windows資源管理器

您不會獲得地址欄的靈活性,但是如果您正在尋找Java中的非樹狀文件選擇器,那么它也可以瀏覽/查看隱藏的文件/文件夾-那么就足夠了

約翰·麥卡錫的答案似乎是最好的。 這里有一些建議。

import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.Image;

在左上角添加圖像。 使用“ getResourceAsStream”很重要,在導出為Runnable jar后,您會注意到:

Display display = new Display();
Shell shell = new Shell(display);
InputStream inputImage = getClass().getResourceAsStream("/app/launcher.png");
if (inputImage != null) {
    shell.setImage(new Image(display, inputImage));
}

用戶的主目錄:

String filterPath = System.getProperty("user.home");

獲取絕對路徑名,而不是依賴於過濾器的路徑名,這在其他驅動器上是錯誤的。

String absolutePath = dialog.open();

由於Swing模擬了各種L&F,因此我認為最好的選擇是將JRE升級到最新版本,並希望JFileChooser UI已更新。

JFileChooser在使用Swing時總是有些奇怪,也有點慢。

嘗試使用SWT的filechooser或將C調用包裝在JNA中。

暫無
暫無

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

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