2014-05-05 62 views
2

我已經想出瞭如何按文件類型進行篩選,但我無法弄清楚如何在文件名文本字段中鍵入我的鍵盤時篩選出文件。如果我在我的目錄1000個文件,其中兩個以字母q那麼我希望,當我在JFileChooser鍵入單詞q它會過濾掉不q這開頭的文件應該繼續輸入,並且應該選擇最好的匹配。這沒有典範嗎?似乎每個JFileChooser問題和教程都只涉及按文件類型而不是按名稱進行過濾。JFileChooser在輸入時按名稱篩選文件

+0

類似[this](http://www.javaworld.com/article/2075004/core-java/speed-up-file-searching-in-jfilechooser。HTML)? –

+0

那篇文章是從2001年開始的,並且聲稱在1.4版本中JFileChooser有一個內置的輸入選擇器。我一直無法找到這個。這篇文章也有許多問題。首先,「findJList」方法是駭人聽聞的。其次,沒有完整的代碼示例。第三,也是最後一個,你輸入時從視圖中過濾掉文件的行爲沒有被解決。現代Java中必須有一種更優雅的方式來實現這種行爲。 – smuggledPancakes

+0

您是否知道,如果您選擇一個文件並鍵入一個字母序列,它會爲您導航到以該序列開頭的文件? – user1803551

回答

1

這是可行的(對於金屬LAF)。雖然這本身就是一個可怕的解決方案,但其他選項並不令人開胃。

public class FilterChooser { 

    JFileChooser chooser = new JFileChooser(); 
    JTextField tf = (JTextField) ((JPanel) ((JPanel) chooser.getComponent(3)).getComponent(0)).getComponent(1); 

    FilterChooser() { 

     tf.getDocument().addDocumentListener(new DocumentListener() { 

      public void insertUpdate(DocumentEvent e) { 

       modifyFilter(); 
      } 

      public void removeUpdate(DocumentEvent e) { 

       modifyFilter(); 
      } 

      public void changedUpdate(DocumentEvent e) { 

       modifyFilter(); 
      } 
     }); 

     JFrame f = new JFrame(); 
     chooser.showOpenDialog(f); 

     f.setLocationRelativeTo(null); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.pack(); 
     f.setVisible(true); 
    } 

    void modifyFilter() { 

     final String text = tf.getText(); 
     chooser.setFileFilter(new FileFilter() { 

      @Override 
      public String getDescription() { 

       return null; 
      } 

      @Override 
      public boolean accept(File f) { 

       return (f.isDirectory() || f.getName().startsWith(text)); 
      } 
     }); 
    } 

    public static void main(String[] args) { 

     new FilterChooser(); 
    } 
} 

說明和解釋:

  • 文本框在一個JFileChooser在MetalFileChooserUI類作爲private場,因此沒有簡單的方法來達到其聲明。我把它做成tf我的方式,因爲我做了我的功課,並檢查它的位置 - 如果佈局改變(在未來多年內不會發生由於向後兼容性)這休息。您也可以遞歸地遍歷子組件。
  • 我只爲文件設置了過濾器。如果您希望將其應用於目錄,請更改FileFilteraccept方法。
  • 該過濾器是目前實施的區分大小寫。您可以通過更改FileFilteraccept方法來修改此行爲。
  • 我添加了空框架,所以JVM在關閉時會退出(文件選擇器,作爲對話框,不會這樣做)。
  • 根據大圖,根據需要設置字段和方法的修飾符。
+0

This Works!我有一個問題,如果我點擊一個文件,然後在目錄上點擊它,然後再次單擊該文件,fileChooser中的選擇消失。我難住爲什麼會發生這種情況...... – smuggledPancakes

+0

嗯......是的。它也會在您第一次選擇文件時發生。會發生什麼情況是,無論何時更改過濾器,文件和文件夾列表都會刷新,並且您丟失了當前選擇。它實際上也是在你鍵入的時候發生的,但在這種情況下你不能注意到它。如果你願意的話,選擇一個文件可能不會自動把它的名字放到字段中。 – user1803551

+0

在設置新過濾器和列表刷新後,Iv'e試圖重新選擇文件,但並不那麼容易。由於某種原因'invokeLater'在這裏沒有做好這項工作。有可以採取的絕望措施,有什麼想法? – user1803551

1

我想爲JFileChooser實施全面的自動完成可能不是微不足道的。您需要訪問選擇器的JTextField,但這不是現成的(儘管不是不可能的)。然後,您可以將自定義DocumentFilter應用到該字段,然後在用戶鍵入時自動填充(並部分選擇該單詞的後端)。

延伸閱讀: http://docs.oracle.com/javase/tutorial/uiswing/components/generaltext.html#filter

然而,這似乎是很多工作。

相反,你知道JFileChooser允許你創建一個過濾器嗎?只需調出選擇器,輸入'q*',按ENTER,選擇器將只顯示以'q'開頭的文件。

+0

剛剛描述的行爲*效果很好。我想讓每個擊鍵都會發生這種行爲,而不僅限於添加*和敲擊輸入。那可能嗎?我對全面自動完成不感興趣。我想在輸入時進行過濾。 – smuggledPancakes

+0

'我對全面自動完成不感興趣。我想按照我的輸入進行過濾。「我看不出有什麼不同。你能解釋一下嗎? – splungebob

+1

我想過濾,因爲我輸入。 ==自動完成對我來說,但這些功能默認使用startWith,不包含,不能,我認爲那裏沒有問題,但正如所描述的@splungebob不容易,並需要努力 – mKorbel

0

我有我想要的行爲。我仍然無法相信這是怎麼一回事,但我猜Swing社區中沒有人認爲讓JFileChooser具有這種行爲或者具有更好的實現它的鉤子是合適的。謝謝user1803551你的回答,我接受你的回答,我張貼我的意思是爲了展示我如何調整你的行爲以獲得我想要的行爲。

public void setupListeners() 
{ 
    JFileChooser chooser = new JFileChooser(); 
    JTextField fileChooserTextField = (JTextField) ((JPanel) ((JPanel) chooser.getComponent(3)).getComponent(0)).getComponent(1); 

    chooser.addKeyListener(new KeyListener() 
    { 
     @Override 
     public void keyTyped(KeyEvent e) 
     { 
     } 
     @Override 
     public void keyReleased(KeyEvent e) 
     { 
      filterAsYouType(fileChooserTextField, chooser); 
     } 
     @Override 
     public void keyPressed(KeyEvent e) 
     { 
     } 
    }); 
} 

    private void filterAsYouType(final JTextField tf, final JFileChooser chooser) 
    { 
    final String text = tf.getText(); 
    chooser.setFileFilter(new FileFilter() 
    { 
     @Override 
     public boolean accept(File f) 
     { 
      if(text.equals("") 
      { 
      return true; 
      } 
      if(f.getName().equals(text)) 
      { 
      chooser.setSelectedFile(f); 
      tf.setCaretPosition(text.length()); 
      } 
      if(f.getName().startsWith(text)) 
      { 
      return true; 
      } 
      return false; 
     } 
     @Override 
     public String getDescription() 
     { 
      return null; 
     } 
    }); 
    } 
} 
+0

由於您只在'KeyListener'中實現了1個方法,所以最好使用'KeyAdapter'。此外,不知道爲什麼你需要檢查文本等於「」,空字符串自動工作;你在第二個if中缺少'return true'。 – user1803551

+0

另外,我認爲KeyListener需要添加到JTextField中,而不是選擇器 –