开发者

keyPressed Listener produces strange behaviour

I have a series of Text- and Comboboxes along a jTable. I use the input from the boxes to filter the results of a JPQL-query, which are displayed on the jTable. Now, the idea was to automate the process, so that every time the user types a character in a box, the app sends the query automatically and updates the jTable with the filtered results. I tried doing it like this:

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

setFilters() and displayResults() are the methods that respectively set the parameters and the query and get the ResultList and update the jTable. I then added the keyPressed to all relevant Textboxes, along with some System.out.println lines for debugging. What happens is following: when i enter the first character nothing happens. If i enter a second character the KeyListener works and sends the query, but filters only with the second character, the first one is ignored. That´s my first weirdness. The second one is, looking at my console i realized the query is beeing sent 6 times for every for every succesful Key Listened. Help would be greatly appreciated. On second thought, I´m also inserting my setFilters() and 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();
}

Thanks in advance !


The problem is that the Document used by the text field has not been updated when the keyPressed event is generated. You could listen for the keyTyped event, however I don't recommend this as it is not the best solution and Swing provides a better API to use.

The better way to do this is to use a DocumentListener which is specifically designed for this purpose. Read the section from the Swing tutorial on How to Write a Document Listener for an example and explanation.


Here's pretty much how to do it. A couple of benefits for you using this approach instead of the keyPressed is that it will work also when you paste some text into the fields and it's easy to avoid doing all your filtering on deletes etc.

// 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
    }
}

And to avoid doing search and filter round trips on every weird thing your users might input into the text fields you should consider doing your own implementation of PlainDocument that only accepts certain characters.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜