keyPressed Listener产生奇怪的行为

时间:2011-03-02 10:02:08

标签: java swing keylistener

我在jTable上有一系列文本和组合框。我使用框中的输入来过滤JPQL查询的结果,这些结果显示在jTable上。现在,我们的想法是自动化流程,以便每次用户在框中键入字符时,应用程序会自动发送查询并使用筛选结果更新jTable。我尝试这样做:

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

setFilters()和displayResults()是分别设置参数和查询并获取ResultList并更新jTable的方法。然后我将keyPressed添加到所有相关的Textboxes,以及一些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();
}

提前致谢!

2 个答案:

答案 0 :(得分:3)

问题是当生成keyPressed事件时,文本字段使用的文档尚未更新。您可以监听keyTyped事件,但我不建议这样做,因为它不是最佳解决方案,Swing提供了更好的API使用。

更好的方法是使用专门为此目的而设计的DocumentListener。阅读How to Write a Document Listener上Swing教程中的部分,以获取示例和解释。

答案 1 :(得分: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);
        }
    }
}