Java 是否禁用JFileChooser中的打开按钮?

Java 是否禁用JFileChooser中的打开按钮?,java,swing,jfilechooser,Java,Swing,Jfilechooser,我扩展了一个JFileChooser并覆盖了approveSelection方法,因此当用户选择一个无效目录,然后单击打开按钮时,JOptionPane中将显示一条错误消息。但是我想让我的JFileChooser更加用户友好,当用户单击无效目录时,使“打开”按钮变为禁用,然后当用户单击有效目录时,使其重新启用。是否可以进一步自定义我的JFileChooser并访问“打开”按钮,以便我可以相应地更改按钮的状态(可能通过侦听目录选择的侦听器) 当检测到文件/目录上的任何选择更改时,可以通过调用cho

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


当检测到文件/目录上的任何选择更改时,可以通过调用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();
    }
});
但这可能会让用户感到困惑,最好使用自定义文件过滤器,只显示所需的文件/目录:

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 () );
编辑: 我找到了一种禁用按钮的方法,通过迭代组件并获取打开按钮的句柄:

例如:

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);
      }
    }     
}
myChooser.setFileSelectionMode(JFileChooser.FILES\u和\u目录);
myChooser.addPropertyChangeListener(新的PropertyChangeListener(){
公共作废属性更改(属性更改事件evt){
if(JFileChooser.SELECTED\u FILE\u CHANGED\u PROPERTY.equals(evt.getPropertyName())){
File File=(File)evt.getNewValue();
如果(file!=null&&file.isFile()){
setOpenButtonState(myChooser,false);
}
else if(文件!=null){
setOpenButtonState(myChooser,true);
System.out.println(file.getName());
}
}
myChooser.repaint();
}
});
公共静态void setOpenButtonState(容器c,布尔标志){
int len=c.getComponentCount();
对于(int i=0;i
正如Wajdy Essam已经回答的那样,您通常可以使用

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

我写了一个快速解决方案,在大多数情况下都能奏效

此外,您还可以完全访问文件选择器的取消和批准按钮

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;
}
}
我还建议使用来验证所选文件,而不是覆盖
approveSelection()

是否禁用JFileChooser中的打开按钮


更好的是,安装一个自定义文件来隐藏无效目录。查看覆盖情况。

为什么不使用文件过滤器呢。它甚至不允许用户选择无效的目录。看,我有相同的要求,但对我来说,我只需要允许选择满足某些条件的目录。我不能使用文件过滤器,因为如果我使用了,用户将无法在文件系统的任何位置导航!我需要允许完整目录导航,但仅允许选择(即,单击“打开”按钮)符合我标准的目录。有什么想法吗?@MatthewWise A
FileSystemView
可以显示文件和目录。是的,但我需要显示所有目录以允许完全导航,但只能选择某些目录,即单击“打开”按钮。我的解决方法是重写approveSelection(),将条件逻辑放在此处,如果所选目录不满足条件,则显示错误消息。希望这能让我更清楚地了解我需要实现什么…很好的示例,但不要使用
b.getText().equals(“Open”)
,使用
b.getText().equals(chooser.getApproveButtonText())
来支持国际化。
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;
}
}