0

在我之前的两篇文章一篇文章之后,以下代码将打开常规文件浏览器而不是展开的文件浏览器:

public class GuiHandler extends javax.swing.JFrame {
    // data members
    private DataParser xmlParser = new DataParser();
    private File newFile;
    JFileChooser jfc = new JFileChooser();

    // more code 

    public void launchFileChooser() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch(Exception e) {
                    e.printStackTrace();
                }
                jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
                jfc.setAcceptAllFileFilterUsed(false);
                if (jfc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
                    newFile = jfc.getSelectedFile();
            }
        });
    }

    // more code 

    private void XMLfilesBrowserActionPerformed(java.awt.event.ActionEvent evt) {       
        launchFileChooser();
        xmlParser.getNodeListFromFile(newFile);
        // here the code has the below problems 

问题:

  1. 当我点击一个按钮时,代码会打开一个常规文件浏览器open XML file;它仍然允许我选择一个文件。
  2. 它抛出一个异常:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: File cannot be null
    at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:198)

jfc如果是数据成员,为什么它会打开常规浏览器,而当它是局部变量时,会打开扩展的浏览器?

4

2 回答 2

2

关于常规文件选择器与扩展文件选择器,请确保在调用UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());之前先调用new JFileChooser();。实际上,除非您允许用户在应用程序执行期间更改外观 (L&F),否则请main在创建任何 Swing 组件之前将 L&F 设置为接近应用程序执行的开头,就像在方法中一样。根据我的经验,不这样做会导致一些奇怪的 UI 行为。

当你有JFileChooser作为局部变量的时候launchFileChooserUIManager.setLookAndFeel在之前被调用new JFileChooser。什么时候JFileChooser是类成员变量(又名数据成员),UIManager.setLookAndFeel在之后调用new JFileChooser;在后一种情况下,在JFileChooser实例化的实例时GuiHandler创建。


关于IllegalArgumentException使用SwingUtilities.invokeAndWaitinlaunchFileChooser而不是SwingUtilities.invokeLater. 更好的是,如果您确定launchFileChooser将始终在事件调度线程上发生,则无需调用SwingUtilities.invokeAndWaitSwingUtilities.invokeLater


您可能还想使用文件过滤器:

jfc.setFileFilter(new FileNameExtensionFilter("XML files (*.xml)", "xml"));

以下是展示上述概念的SSCE :

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.filechooser.FileNameExtensionFilter;

public class GuiHandler extends JFrame {
    public static void main(String[] args) throws Exception {
        // call UIManager.setLookAndFeel early in application execution
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        JFrame frame = new GuiHandler();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private final JFileChooser jfc;

    public GuiHandler() {
        this.jfc = new JFileChooser();
        this.jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        this.jfc.setFileFilter(new FileNameExtensionFilter("XML files (*.xml)", "xml"));

        final JButton button = new JButton("Open XML file");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                xmlFilesBrowserActionPerformed();
            }
        });
        add(button);

        pack();
    }

    protected void xmlFilesBrowserActionPerformed() {
        final File xmlFile = getXmlFile();
        if (xmlFile != null) {
            System.out.println(xmlFile); // process XML file
        }
    }

    private File getXmlFile() {
        // At this point we should be on the event dispatch thread,
        // so there is no need to call SwingUtilities.invokeLater
        // or SwingUtilities.invokeAndWait.
        if (this.jfc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            return this.jfc.getSelectedFile();
        }
        return null;
    }
}
于 2012-06-06T05:08:05.067 回答
0

我不确定您所说的“扩展的”是什么意思,但我假设您指的是文件过滤器。在没有任何文件过滤器的情况下,我猜它默认显示所有文件。在打开对话框之前尝试添加以下代码。

jfc.setFileFilter(new javax.swing.filechooser.FileFilter(){
    public boolean accept(File f){
        return  f.isDirectory() || f.getName().toLowerCase().endsWith(".xml");
    }
    public String getDescription(){
        return "XML File";
    }
})
于 2012-06-06T05:45:01.760 回答