我扩展了JFileChooser
并覆盖了approveSelection
方法,以便当用户选择无效目录然后单击“打开”按钮时,将显示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);
}
}
答案 0 :(得分:10)
当检测到文件/目录上的任何选择更改时,您可以通过调用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);
}
}
}
答案 1 :(得分:1)
正如Wajdy Essam已经回答的那样,你通常可以使用
隐藏/显示控制按钮javax.swing.JFileChooser#setControlButtonsAreShown(boolean)
但是这种方法并不适用于所有的外观和感觉,至少不适用于我正在使用的那些。
我写了一个快速解决方法,在大多数情况下都可以使用。
此外,您可以完全访问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验证所选文件,而不是覆盖approveSelection()
答案 2 :(得分:1)
在JFileChooser中禁用“打开”按钮?
更好的是,安装隐藏无效目录的自定义FileSystemView
。请考虑覆盖isHiddenFile(File)
。