JFileChooser.getSelectedFile() return 实现自定义操作按钮时为空

JFileChooser.getSelectedFile() return null when implement custom action button

我有一个 JFrameJFileChooser。需要有一个自定义导入按钮,而不是默认的文件选择器操作按钮。

如果我使用自定义操作按钮,如果我在文件名文本框中输入值,JFileChooser.getSelectedFile() return 为空。而如果我单击该文件并单击自定义导入,我可以获得我选择的文件。

这里我包含了重现这个的示例代码

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class FileChooserDemo extends JPanel
                             implements ActionListener {
    private static final long serialVersionUID = 1L;
    JFileChooser importFileChooser;
    JFrame frame;

    private void createAndShowGUI() {
        //Create and set up the window.
        frame = new JFrame("FileChooserDemo");

        JPanel inputJobDetailsPanel = new JPanel(new BorderLayout(0,5));

        importFileChooser = new JFileChooser();
        importFileChooser.setControlButtonsAreShown(false);
        importFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        importFileChooser.setMultiSelectionEnabled(false);
        inputJobDetailsPanel.add(importFileChooser, BorderLayout.CENTER);

        GridBagLayout importButtonPanelLayout = new GridBagLayout();
        importButtonPanelLayout.columnWidths = new int[] {150};
        importButtonPanelLayout.rowHeights = new int[] {30};

        JPanel importButtonPanel = new JPanel();
        importButtonPanel.setLayout(importButtonPanelLayout);

        JButton importButton = new JButton("Custom Import");
        importButton.setActionCommand("import");
        importButton.addActionListener(this);
        importButtonPanel.add(importButton, new GridBagConstraints());

        JButton OtherButton = new JButton("Other Action");
        OtherButton.setActionCommand("otherImport");
        OtherButton.addActionListener(this);
        importButtonPanel.add(OtherButton, new GridBagConstraints());

        inputJobDetailsPanel.add(importButtonPanel, BorderLayout.PAGE_END);

        frame.add(inputJobDetailsPanel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new FileChooserDemo().createAndShowGUI();
            }
        });
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if(command.equals("import")) {
            if(importFileChooser.getSelectedFile() == null) {
                JOptionPane.showMessageDialog(frame, "You entered file name but getSelectedFile() return null");
            }else {
                JOptionPane.showMessageDialog(frame, "Chosen File Name: " + importFileChooser.getSelectedFile().getName());
            }
        }else {
            JOptionPane.showMessageDialog(frame, "You clicked other action");
        }

    }
}

O/P:

重现步骤:

  1. 运行 申请
  2. 在 "File Name" 文本框中输入有效的文件名
  3. 点击自定义导入
  4. 现在可以看到"You entered file name but getSelectedFile() return null"

注意:如果我使用 importFileChooser.setControlButtonsAreShown(true);

启用默认操作按钮

即使我在文本框中输入而无需单击文件,我也可以获得 getSelectedFile()。

实际上我正在尝试编写一个自动化脚本,所以我只能通过 "File Name" 文本框输入文件路径。

想知道不用点击文件就可以通过 getSelectedFile() 获取文件吗??

因为并非所有外观实现都支持在文本字段中直接输入文件名*,您可能需要考虑另一种设计:

  • Less modal:如Providing an Accessory Component所示,您可以在面板中添加附件组件"with more controls on it such as checkboxes that toggle between features."具体细节取决于启用的功能通过自定义导入其他操作

  • 更多模式:在用户批准特定部分后显示一个模式对话框。

建议的中间方法 具有以下限制:

  1. 假设 javax.swing.plaf.metal.MetalLookAndFeel.

  2. ActionEvent:“如果任何特定 ActionEvent 实例的 id 参数不在 ACTION_FIRSTACTION_LAST.

  3. ActionEvent: "A null command string is legal, but not recommended."

* 例如com.apple.laf.AquaLookAndFeel

终于得到了预期的输出。调用默认文件选择器按钮动作侦听器

@SuppressWarnings("serial")
@Override
public void actionPerformed(ActionEvent e) {
    String command = e.getActionCommand();
    if(command.equals("import")) {
        if(importFileChooser.getSelectedFile() == null) {
            MetalFileChooserUI ui = (MetalFileChooserUI) importFileChooser.getUI();
            for(ActionListener a: ui.getDefaultButton(importFileChooser).getActionListeners()) {
                a.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null) {
                          //Nothing need go here, the actionPerformed method (with the above arguments) will trigger the respective listener
                  });
            }
        }

        if(importFileChooser.getSelectedFile() != null) {
          JOptionPane.showMessageDialog(frame, "Chosen File Name: " + importFileChooser.getSelectedFile().getName());
        }
        else {
            JOptionPane.showMessageDialog(frame, "You entered file name but getSelectedFile() return null");
        }
    }
    else {
        JOptionPane.showMessageDialog(frame, "You clicked other action");
    }
}