2012-12-27 35 views
2

我擴展了JFileChooser並覆蓋了approveSelection方法,以便當用戶選擇一個無效目錄然後單擊打開按鈕時,將顯示JOptionPane中的錯誤消息。但是我想讓我的JFileChooser更方便用戶使用,並且當用戶點擊一個無效的目錄,然後在用戶點擊一個有效的目錄時重新啓用時,打開按鈕被禁用。是否有可能進一步定製我的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); 
    } 

} 
+2

爲什麼你不使用FileFilter。它甚至不會讓用戶選擇一個無效的目錄。見http://docs.oracle.com/javase/6/docs/api/javax/swing/JFileChooser.html#setFileFilter%28javax.swing.filechooser.FileFilter%29 –

回答

9

可以隱藏接受/調用chooser.setControlButtonsAreShown(假)取消按鈕檢測上的文件/目錄中的任何改變選擇時:

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

很好的例子,但不要使用'b.getText ().equals(「Open」),使用'b.getText()。equals(chooser.getApproveButtonText())'來支持國際化。 – Stephan

1

由於Wajdy埃薩姆已經回答了你通常可以隱藏/顯示用

的controlbuttons

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驗證所選文件而不是在JFileChooser所覆蓋approveSelection()

1

禁用打開按鈕?

更妙的是,安裝定製的FileSystemView無效的目錄。看看這個覆蓋isHiddenFile(File)

+1

我有同樣的要求,但對我而言,我只需要允許選擇滿足特定條件的目錄。我無法使用文件過濾器,因爲如果我這樣做了,用戶將無法在文件系統上的任何位置導航!我需要允許完整的目錄導航,但只允許選擇即如果它滿足我的標準,點擊一個目錄的打開按鈕。 任何想法? –

+0

@MatthewWise一個'FileSystemView'可以顯示文件**和目錄** –

+0

是的,但我需要所有的目錄**顯示**以允許完全導航,但只有某些是**可選**即通過點擊打開按鈕。我的解決方法是重寫approveSelection(),將標準邏輯放在這裏,如果所選目錄不符合標準,則顯示錯誤消息。希望這可以讓我更清楚我需要實現的內容...... –