java Swing 是否支持 Windows 7 风格的文件选择器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5703825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:23:57  来源:igfitidea点击:

Does Swing support Windows 7-style file choosers?

javaswingfilechooser

提问by Pops

I just added a standard "Open file" dialog to a small desktop app I'm writing, based on the JFileChooserentry of the Swing Tutorial. It's generating a window that looks like this:

我刚刚根据Swing 教程条目向我正在编写的小型桌面应用程序添加了一个标准的“打开文件”对话框。它正在生成一个如下所示的窗口:JFileChooser

screenshot of unwanted/XP-style window

不需要的/XP 样式窗口的屏幕截图

but I would prefer to have a window that looks like this:

但我更喜欢有一个看起来像这样的窗口:

screenshot of desired/7-style window

所需/7 样式窗口的屏幕截图

In other words, I want my file chooser to have Windows Vista/Windows 7's style, not Windows XP's. Is this possible in Swing? If so, how is it done? (For the purposes of this question, assume that the code will be running exclusively on Windows 7 computers.)

换句话说,我希望我的文件选择器具有 Windows Vista/Windows 7 的风格,而不是 Windows XP 的风格。这在 Swing 中可能吗?如果是这样,它是如何完成的?(对于这个问题,假设代码将专门在 Windows 7 计算机上运行。)

采纳答案by John McCarthy

It does not appear this is supported in Swing in Java 6.

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

Currently, the simplest way I can find to open this dialog is through SWT, not Swing. SWT's FileDialog (javadoc) brings up this dialog. The following is a modification of SWT's FileDialog snippetto use an open instead of save dialog. I know this isn't exactly what you're looking for, but you could isolate this to a utility class and add swt.jar to your classpath for this functionality.

目前,我能找到的打开此对话框的最简单方法是通过 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 ();
    }
} 

回答by Alexey Ivanov

Even native Windows applications can get this type of dialog displayed on Windows 7. This is usually controlled by flags in OPENFILENAMEstructure and its size passed in a call to WinAPI function GetOpenFileName. Swing (Java) uses hooks to get events from the Open File dialog; these events are passed differently between Windows?XP and Windows?7 version.

甚至本机 Windows 应用程序也可以在 Windows 7 上显示这种类型的对话框。这通常由OPENFILENAME结构中的标志及其在调用 WinAPI 函数时传递的大小控制GetOpenFileName。Swing (Java) 使用钩子从打开文件对话框中获取事件;这些事件在 Windows?XP 和 Windows?7 版本之间以不同的方式传递。

So the answer is you can't control the look of FileChooser from Swing. However, when Java gets support for this new look, you'll get the new style automatically.

所以答案是您无法从 Swing 控制 FileChooser 的外观。但是,当 Java 获得对这种新外观的支持时,您将自动获得新样式。

Another option is to use SWT, as suggested in this answer. Alternatively you can use JNA to call Windows?API or write a native method to do this.

另一种选择是使用 SWT,如本答案中所建议。或者,您可以使用 JNA 调用 Windows?API 或编写本机方法来执行此操作。

回答by Luke Usherwood

Java 8 may finally bring a solution to this, but unfortunately (for Swing apps) it comes only as the JavaFX class FileChooser:

Java 8 最终可能会为此提供解决方案,但不幸的是(对于 Swing 应用程序)它仅作为 JavaFX 类FileChooser 出现

I've tested this code from hereand it indeed pops a modern dialog (Windows 7 here):

我已经从这里测试了这段代码,它确实弹出了一个现代对话框(此处为 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);

To integrate this into a Swing app, you'll have to run it in the javafx thread via Platform.runLater(as seen here).

这种集成到Swing应用程序,你必须在通过JavaFX的线程中运行它Platform.runLater(如看到这里)。

Please note that this will need you to initialize the javafx thread (in the example, this is done at the scene initialization, in new JFXPanel()).

请注意,这将需要您初始化 javafx 线程(在示例中,这是在场景初始化时完成的,在 中new JFXPanel())。

To sum up, a ready to run solution in a swing app would look like this :

总而言之,一个可以在 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);
});

回答by Andrew Thompson

A bit of a hack, and slightly less empowered than the Swing version, but have you considered using a java.awt.FileDialog? It should not just looklike the Windows file chooser, but actually beone.

有点 hack,并且比 Swing 版本的功能稍差,但是您是否考虑过使用java.awt.FileDialog? 它不应该只是看起来像 Windows 文件选择器,而实际上一个。

回答by mezmo

I don't believe Swing would cover that though it may, if it doesn't you may need to look at something like SWT, which would make use of the actual native component, or do a custom UI element, like something out of the "Filthy Rich Clients" book.

我不相信 Swing 会涵盖这一点,尽管它可能会涵盖,如果没有,您可能需要查看像 SWT 这样的东西,它会使用实际的本机组件,或者做一个自定义的 UI 元素,比如某些东西“肮脏的富客户”一书。

回答by mKorbel

good question +1 , looks like as they "forgot" to implements something for Win7 (defaultLookAndFeel) into Java6, but for WinXP works correclty, and I hope too, that there must exists some Method/Properties for that

好问题 +1 ,看起来他们“忘记”将 Win7(defaultLookAndFeel)的某些东西实现到 Java6 中,但对于 WinXP 来说是正确的,我也希望,必须存在一些方法/属性

anyway you can try that with this code,

无论如何,您可以使用此代码尝试一下,

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() {
    }
}

回答by User Rebo

John McCarthy's answer seems to be the best. Here some suggestions.

约翰麦卡锡的答案似乎是最好的。这里有一些建议。

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

Add image on top left corner. It's important that you use "getResourceAsStream", you'll notice after export as Runnable jar:

在左上角添加图像。使用“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));
}

User's home directory:

用户的主目录:

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

Get absolut pathname instead of filter-dependent pathname, which is wrong on other drive.

获取绝对路径名而不是依赖于过滤器的路径名,这在其他驱动器上是错误的。

String absolutePath = dialog.open();

回答by Rohan

Couldn't make this work for directories though!! The DirectoryDialog throws us back to the tree style directory chooser which is the same as the one listed in the question. The problem is that it does not allow me to choose/select/open hidden folders. Nor does it allow for navigation to folders like AppData, ProgramData etc..

但是不能使这对目录起作用!!DirectoryDialog 将我们带回到与问题中列出的目录选择器相同的树样式目录选择器。问题是它不允许我选择/选择/打开隐藏文件夹。它也不允许导航到 AppData、ProgramData 等文件夹。

The Windows 7 style filedialog (swt) does allow navigation to these folders, but then again, does not allow for folder selection :(

Windows 7 风格的文件对话框 (swt) 确实允许导航到这些文件夹,但同样不允许选择文件夹:(

UpdateTo view hidden folders use JFileChooser and have setFileHidingEnabled(false). The only mandate with this is that users need to have 'show hidden files, folders and drives' selected in the

更新要查看隐藏文件夹,请使用 JFileChooser 并具有setFileHidingEnabled(false). 唯一的要求是用户需要在“显示隐藏的文件、文件夹和驱动器”中选择

Folder Options -> View

文件夹选项 -> 查看

of Windows Explorer

Windows 资源管理器

You won't get the flexibility of an address bar, but if you were looking around for a non-tree like file chooser in Java, which also lets you browse/view Hidden files/folder - then this should suffice

您将无法获得地址栏的灵活性,但是如果您在 Java 中寻找类似非树的文件选择器,它还可以让您浏览/查看隐藏的文件/文件夹 - 那么这应该就足够了

回答by meverett

JFileChooser has always been a bit odd looking with Swing, also a bit slow.

JFileChooser 在 Swing 中看起来总是有点奇怪,也有点慢。

Try using SWT's filechooser or you could wrap the C calls in JNA.

尝试使用 SWT 的文件选择器,或者您可以将 C 调用包装在 JNA 中。

回答by qwerty

Since Swing emulates various L&F's, I guess your best bet would be to upgrade your JRE to the very latest and hope that the JFileChooser UI has been updated.

由于 Swing 模拟各种 L&F,我想最好的办法是将 JRE 升级到最新版本,并希望 JFileChooser UI 已更新。