在JFileChooser中禁用“打开”按钮?

我扩展了一个JFileChooser并覆盖了approveSelection方法,以便当用户选择一个无效的目录然后单击Open按钮时,将显示JOptionPane的错误消息。 但是我想让我的JFileChooser更加用户友好,并且当用户点击无效目录然后在用户点击有效目录时重新启用时,将禁用“打开”按钮。 是否可以进一步自定义我的JFileChooser并访问“打开”按钮,以便我可以相应地更改按钮的状态(可能通过侦听目录选择的侦听器)?

 public class MyFileChooser extends JFileChooser { private final JFrame mainFrame; public MyFileChooser(JFrame mainFrame) { this.mainFrame = mainFrame; setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); } @Override public void approveSelection() { if (/* directory is valid */) { super.approveSelection(); return; } JOptionPane.showMessageDialog(mainFrame, "Invalid directory", "Error", JOptionPane.ERROR_MESSAGE); } } 

您可以通过在检测到文件/目录上的任何选择更改时调用chooser.setControlButtonsAreShown(false)来隐藏接受/取消按钮:

 myChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); myChooser.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(evt.getPropertyName())) { File file = (File) evt.getNewValue(); if (file != null && file.isFile()) { // your condition myChooser.setControlButtonsAreShown(false); } else if ( file != null ) { System.out.println(file.getName()); myChooser.setControlButtonsAreShown(true); } } myChooser.repaint(); } }); 

但它可能会使用户感到困惑,它更好地制作自定义FileFilter并只显示您需要的文件/目录:

 public static class MyDirectoryFilter extends javax.swing.filechooser.FileFilter { @Override public boolean accept( File file ) { return file.isDirectory() && customeCondition(file) ; } @Override public String getDescription() { return "this only my custom dir"; } } myChooser.setFileFilter( new MyDirectoryFilter () ); 

编辑 :我找到了一种方法来禁用按钮,通过迭代组件并获得打开按钮的句柄: http : //www.coderanch.com/t/468663/GUI/java/Disabling-Enabling-level-button-folder

例:

 myChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); myChooser.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(evt.getPropertyName())) { File file = (File) evt.getNewValue(); if (file != null && file.isFile()) { setOpenButtonState(myChooser, false); } else if ( file != null ) { setOpenButtonState(myChooser, true); System.out.println(file.getName()); } } myChooser.repaint(); } }); public static void setOpenButtonState(Container c, boolean flag) { int len = c.getComponentCount(); for (int i = 0; i < len; i++) { Component comp = c.getComponent(i); if (comp instanceof JButton) { JButton b = (JButton) comp; if ( "Open".equals(b.getText()) ) { b.setEnabled(flag); } } else if (comp instanceof Container) { setOpenButtonState((Container) comp, flag); } } } 

正如Wajdy Essam已经回答的那样,你通常可以隐藏/显示控制按钮

javax.swing.JFileChooser中#setControlButtonsAreShown(布尔值)

但是这种方法并不适用于所有的外观,至少不是我正在使用的那些。

我写了一个快速的解决方法,在大多数情况下都可以使用。

此外,您可以完全访问FileChooser的cancel和approveButton。

 public class JFileChooserTest extends JFileChooser { private JButton approveButton, cancelButton; public JFileChooserTest() { // Lookup the Buttons if (approveButton == null) { approveButton = lookupButton(JFileChooserTest.this, getUI().getApproveButtonText(this)); } if (cancelButton == null) { cancelButton = lookupButton(JFileChooserTest.this, UIManager.getString("FileChooser.cancelButtonText")); } setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); //Creating the Listener PropertyChangeListener propertyChangeListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { //Do action only if the selected file changed if (evt.getPropertyName().equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) { File newFile = (File) evt.getNewValue(); //Validate the new File boolean validate = validateFile(newFile); //Enable/Disable the buttons if (approveButton != null) { approveButton.setEnabled(validate); } if (cancelButton != null) { cancelButton.setEnabled(validate); } } } }; //Adding the listeners addPropertyChangeListener(SELECTED_FILE_CHANGED_PROPERTY, propertyChangeListener); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); JFileChooserTest test = new JFileChooserTest(); test.showOpenDialog(null); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { Logger.getLogger(JFileChooserTest.class.getName()).log(Level.SEVERE, null, ex); } } }); } /** * Simple validation method; only for testing purpose * * @param f * @return */ private boolean validateFile(File f) { return f != null && !f.getName().startsWith("A"); } /** * Looksup the first JButton in the specific Container (and sub-containers) * with the given text. * * @param c * @param text * @return */ private JButton lookupButton(Container c, String text) { JButton temp = null; for (Component comp : c.getComponents()) { if (comp == null) { continue; } if (comp instanceof JButton && (temp = (JButton) comp).getText() != null && temp.getText().equals(text)) { return temp; } else if (comp instanceof Container) { if ((temp = lookupButton((Container) comp, text)) != null) { return temp; } } } return temp; } } 

我还建议使用javax.swing.filechooser.FileFilter来validation所选文件,而不是覆盖approveSelection()

在JFileChooser中禁用“打开”按钮?

更好的是,安装一个隐藏无效目录的自定义FileSystemView 。 查看重写isHiddenFile(File)