2010-11-19 13 views
3

J'ai une JTable avec quatre colonnes, la première contenant un nombre ou un texte, les trois autres seulement. Je suis en train de filtrer ce tableau avec l'aide d'un RowFilter:"Concaténation" andFilter et orFilter pour RowFilter

sorter = new TableRowSorter<TableModel>(myOwnTableModel); 

Le checkboxFilter je suis arrivé fonctionne bien assez:

sorter.setRowFilter(RowFilter.regexFilter("^[0-9]$", 0)); 

Cette trieuse est activée ou désactiver selon une case à cocher qui est soit définir ou non.
Le deuxième filtrage se produit si un utilisateur met du texte dans un champ de texte. Pour lui-même, cela fonctionne déjà:

String regex = "(?i)" + Pattern.quote(s); // s = input Text of user 
sorter.setRowFilter(RowFilter.regexFilter(regex, 1,2,3)); 

Ce que je ne peux pas faire, c'est d'activer les deux filtres en même temps. Peut-être que je réfléchis bien trop loin, mon idée a été de "concaténer" les deux filtres, le checkboxFilter devrait être "et" l'autre "ou". J'ai essayé plusieurs choses, pour moi le plus prometteur quelque chose comme regardé:

String regex = "(?i)" + Pattern.quote(s); 
bookFilter = RowFilter.regexFilter(regex, 1,2,3); 
sorter.setRowFilter(bookFilter.andFilter(Arrays.asList(
        RowFilter.regexFilter("^[0-9]$", 0)))); 

Malheureusement, cela ne conduit à aucun résultat utilisable. Toutes les idées ont apprécié :)

Répondre

4

La solution est d'ajouter un ActionListener à la JCheckBox de mettre à jour l'état du filtre si la case est basculée et d'ajouter un DocumentListener au document sous-jacent de la JTextField mettre à jour l'état du filtre si le contenu le champ est mis à jour.

L'autre bogue dans votre code est que vous appelez la méthode andFilter statique sur votre instance bookFilter et ne font que passer dans le filtre regex nouvellement construit (à savoir vous que passer dans un paramètre à andFilter). L'utilisation correcte est:

RowFilter andFilter = RowFilter.andFilter(filter1, filter2, etc); 

Exemple événement Listeners

JCheckBox cb = ... 
cb.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
    updateFilters(); 
    } 
}); 

JTextField tf = ... 
tf.getDocument().addDocumentListener(new DocumentListener() { 
    public void insertUpdate(DocumentEvent e) { updateFilters(); } 
    public void removeUpdate(DocumentEvent e) { updateFilters(); } 
    publci void changedUpdate(DocumentEvent e) { updateFilters(); } 
}); 

... puis définir votre méthode updateFilters() pour installer un nouveau filtre en fonction lorsque la case est cochée et si la Le champ de texte est vide ou non.

Exemple Filtre de mise à jour Méthode

public void updateFilters() { 
    if (cb.isSelected()) { 
    if (tf.getText().length() > 0) { 
     // Both filters active so construct an and filter. 
     sorter.setRowFilter(RowFilter.andFilter(bookFilter, checkBoxFilter)); 
    } else { 
     // Checkbox selected but text field empty. 
     sorter.setRowFilter(checkBoxFilter); 
    } 
    } else if (tf.getText().length() > 0) { 
    // Checkbox deselected but text field non-empty. 
    sorter.setRowFilter(bookFilter); 
    } else { 
    // Neither filter "active" so remove filter from sorter. 
    sorter.setRowFilter(null); // Will cause table to re-filter. 
    } 
} 
+0

Cela fonctionne parfaitement, merci! Je l'ai fait deux petits changements: tf.addKeyListener (nouveau KeyAdapter() { \t \t \t @Override \t \t \t publique vide keyReleased (KeyEvent arg0) { \t \t \t \t updateFilters(); \t \t \t} \t \t}); et j'ai dû utiliser la construction suivante pour pouvoir ajouter les deux filtres: sorter.setRowFilter (RowFilter.andFilter (Arrays.asList (bookFilter, checkBoxFilter))); mais je ne sais pas exactement pourquoi, mais comme ça ça marche :) – Hixi