2011-03-02 70 views
1

沿着一個jTable我有一系列的文本和組合框。我使用框中的輸入來過濾jTable上顯示的JPQL查詢的結果。現在,我們的想法是自動化該過程,以便每當用戶在框中鍵入一個字符時,應用程序會自動發送查詢並使用過濾的結果更新jTable。我試圖做這樣的:keyPressed監聽器產生奇怪的行爲

public class MyKeyListener extends KeyAdapter{ 
    public void keyPressed(KeyEvent evt){ 
     setFilters(); 
     displayResults(); }} 

setFilters()和displayResults()是分別設定的參數和查詢,並得到ResultList和更新JTable中的方法。然後,我將keyPressed添加到所有相關的文本框,以及一些用於調試的System.out.println行。接下來會發生什麼:當我輸入第一個字符時什麼也沒有發生。如果我輸入第二個字符,則KeyListener將運行併發送查詢,但僅使用第二個字符進行過濾,第一個字符將被忽略。這是我的第一個怪誕。第二個是,看着我的控制檯,我意識到查詢是每個成功的Key Listened發送6次。幫助將不勝感激。第二個想法,我也插入我的setFilters()和displayResults()。

private void setFilters() { 

    //Auslesen der gesetzten Filter 
    String name=jName.getText()+"%"; 
    String vorname= jVorname.getText()+"%"; 
    String vvname= jVName.getText()+"%"; 
    String vvorname=jVVorname.getText()+"%"; 
    String mname=jMName.getText()+"%"; 
    String strasse=jAdresse.getText()+"%"; 
    String plz=jPlz.getText()+"%"; 
    String ort=jOrt.getText()+"%"; 
    String gruppe=jGruppe.getText()+"%"; 
    String geschlecht=(String) jGeschlecht.getSelectedItem()+"%"; 
    String mvorname=jMVorname.getText()+"%"; 
    String firma=jFirma.getText()+"%"; 



    //Die Query 
    kinderQuery = java.beans.Beans.isDesignTime() ? null : rcwPUEntityManager.createQuery("SELECT k FROM Kinder k " 
      + "INNER JOIN k.vaeter vat " 
      + "INNER JOIN k.muetter mut " 
      + "INNER JOIN k.gruppen gru " 
      + "INNER JOIN k.firmen fir " 
      + "WHERE k.kindName LIKE :name " 
      + "AND k.kindVorname LIKE :vorname " 
      + "AND vat.vaterName LIKE :vname " 
      + "AND vat.vaterVorname LIKE :vvorname " 
      + "AND mut.mutterName LIKE :mname " 
      + "AND mut.mutterVorname LIKE :mvorname " 
      + "AND k.kindStrasse LIKE :strasse " 
      + "AND k.kindPLZ LIKE :plz " 
      + "AND k.kindOrt LIKE :ort " 
      + "AND gru.gruppeName LIKE :gruppe " 
      + "AND k.kindGeschlecht LIKE :geschlecht " 
      + "AND fir.firmaName LIKE :firma "); 


      //Einsetzen der ausgelesenen Strings in die JPQL-Query Parameter 
    kinderQuery.setParameter("name", name); 
    kinderQuery.setParameter("vorname", vorname); 
    kinderQuery.setParameter("vname", vvname); 
    kinderQuery.setParameter("vvorname", vvorname); 
    kinderQuery.setParameter("mname", mname); 
    kinderQuery.setParameter("mvorname", mvorname); 
    kinderQuery.setParameter("strasse", strasse); 
    kinderQuery.setParameter("plz", plz); 
    kinderQuery.setParameter("ort", ort); 
    kinderQuery.setParameter("gruppe", gruppe); 
    kinderQuery.setParameter("geschlecht", geschlecht); 
    kinderQuery.setParameter("firma", firma); 

} 

private void displayResults(){ 
    java.util.Collection data = kinderQuery.getResultList(); 
    System.out.println(data); 
    kinderList.clear(); 
    kinderList.addAll(data); 
    jTable1.repaint(); 
} 

在此先感謝!

回答

3

問題是,當生成keyPressed事件時,文本字段使用的文檔未被更新。你可以監聽keyTyped事件,但是我不推薦這樣做,因爲它不是最好的解決方案,Swing提供了一個更好的API來使用。

更好的方法是使用專門爲此設計的DocumentListener。有關示例和解釋,請參閱How to Write a Document Listener的Swing教程中的部分。

+0

謝謝你們兩位的回答。我承認從未使用過DocumentListener,我將通讀它。 –

0

這裏幾乎是如何做到這一點。一對夫婦使用這種方法,而不是keyPressed對你的好處是,它也將努力當你粘貼一些文本字段,並可以很容易地避免做所有的過濾上刪除等

// in your frame or panel 
Document doc = new PlainDocument(); 
doc.addDocumentListener(new MyDocumentListener()); 

JTextField textField = new JTextField(15); 
textField.setDocument(doc); 

add(textField); 

private class MyDocumentListener implements DocumentListener 
{ 
    public void insertUpdate(DocumentEvent documentEvent) 
    { 
     // Do your stuff here 
     System.out.println("insert detected!"); 
    } 

    public void removeUpdate(DocumentEvent documentEvent) 
    { 
     // ignore this 
    } 

    public void changedUpdate(DocumentEvent documentEvent) 
    { 
     // ignore this 
    } 
} 

,並避免對用戶可能輸入到文本字段中的每一個奇怪的東西進行搜索和過濾,您應該考慮執行您自己的只接受某些字符的PlainDocument。

private class MyDocument extends PlainDocument 
{ 
    @Override 
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException 
    { 
     StringBuilder builder = new StringBuilder(getText(0, getLength())); 
     builder.insert(offs, str); 

     if (builder.toString().matches("[A-Za-z]*")) 
     { 
      super.insertString(offs, str, a); 
     } 
    } 
} 
+0

Swing教程提供和解釋以及一個工作示例。你爲什麼認爲發佈一些沒有做任何事情的代碼片段比教程更好?另外,從Swing教程中的「Text Compnent Features」一節中,您可以找到關於使用文檔過濾器的一節,該過濾器是鍵入時篩選/編輯文本的首選方法。或者你甚至可以使用JFormattedTextField。 – camickr

+0

我還沒有宣佈它是更好的,閱讀教程仍然是一個好主意,我也是一個提高你的答案。然而,通常你不需要一整個教程來解決一個特定的問題,這是很多噪音。獲得針對手頭問題量身定做的具體示例也非常方便,併爲這個特定案例指出了一些好處。你不同意嗎? –

+0

我從來沒有建議你閱讀整個教程,只有顯示如何編寫DocumentListener的部分。你沒有發佈一個具體的例子,因爲你的代碼只是一些不可編譯的隨機行。你的代碼不會被問到這個問題。通常,當教程有一個通用的解決方案時,不需要提供答案。這樣它就會強制發佈來理解這個例子,而不僅僅是複製代碼而不理解它。 「給別人一條魚,他們吃一天,教某人去釣魚,然後他們終身吃東西」。 – camickr