2011-11-03 4 views
0

Se produit si au moins l'une des valeurs (valeurs == valeur dans RowFilter, valeur dans l'entrée) est une décimale. Voici un test défaillant:RowFilter.NumberFilter: impossible de gérer les types de nombres concrets "mixtes"

@Test 
public void testRowFilterNumberMixCore() { 
    TestEntry entry = new TestEntry(1.2f); 
    RowFilter filter = RowFilter.numberFilter(ComparisonType.AFTER, 1, 0); 
    assertTrue(entry + "must be included " + filter, filter.include(entry)); 
} 

La sortie est:

 
junit.framework.AssertionFailedError: 
[entry: 1.2] must be included [RowFilter: ComparisonType = AFTER, comparableValue: 1, comparableClass: class java.lang.Integer] 

La raison est que NumberFilter revient à comparer les chiffres par leur number.longValue() si elles ne sont pas la même classe (et par rapport à l'autre)

Connaissant ce détail, l'échec du test n'est pas étonnant (à l'arrière-plan, n'aurait jamais pensé que ce soit un problème ;-) Un niveau de défense est de s'assurer - dans le client code - que les chiffres à comparer sont de la même classe. Ce n'est pas toujours possible (pensez f.i: un tableColumn avec columnClass Number) Donc je me demande si/comment améliorer le repli. Quelque chose comme:

if (one instanceof Comparable && one.getClass() == other.getClass()) { 
    // same class, use comparator 
    return ((Comparable) one).compareTo(other); 
} 
if (areIntegers(one, other)) { 
    // all integers, use longValue 
    return longCompare(one, other); 
} 
if (areDecimals(one, other)) { 
    // anything to do here? 
} 
// at last resort convert to BigDecimal and compare those: 
BigDecimal bigOne = new BigDecimal(one.toString()); 
BigDecimal bigOther = new BigDecimal(other.toString()); 
return bigOne.compareTo(bigOther); 

Ce faisant, fait passer de test - Je suis un peu méfiant au sujet cachés (lire: inconnu pour moi :) pièges. Tous les avertissements/alternatives sont les bienvenus!

Pour votre information: permuté à OTN's Swing forum

Suivi

mis en œuvre comme indiqué ci-dessus, en attendant maintenant pour les clients de se plaindre - dans ce cas, va pointer du doigt à tous ceux qui ne me prévenir ici :-)

+0

Je peux voir ça ???? http://stackoverflow.com/questions/6187566/problem-formatting-fields-in-a-jtable-differences-between-integer-and-double ??? ou pas – mKorbel

+0

@mKorbel - merci pour le lien. Cela semble un peu sans rapport, si je comprends bien cette question: le formateur aboie si la classe de colonne est différente de la classe garantie dans getColumnClass. Ce que je pense est à prévoir. Cela se résume ici à la comparaison des nombres, la table uniquement en arrière-plan (naturellement, l'un des domaines cibles évidents :-) – kleopatra

Répondre

2

Juste pour mettre un terme à cette (pour l'instant, se fera un plaisir de rouvrir si d'autres réponses/commentaires se présenter :-) - résolu comme indiqué dans la question.

Nous vous remercions de votre intérêt!

3

Je n'ai pas une meilleure réponse, mais l'exemple ci-dessous illustre l'effet. En particulier, un RowFilter basé sur une primitive double est boxed en tant que Double, produisant le tableau attendu ayant values > 1. En revanche, celui basé sur un float est encadré comme Float. Parce que les littéraux de classe ne correspondent pas, include() compare les valeurs long, en filtrant de manière inattendue tous les values < 2 fractionnaires.

import java.awt.BorderLayout; 
import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.util.Arrays; 
import javax.swing.AbstractAction; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.JToggleButton; 
import javax.swing.RowFilter; 
import javax.swing.RowFilter.ComparisonType; 
import javax.swing.table.AbstractTableModel; 
import javax.swing.table.TableRowSorter; 

/** @see http://stackoverflow.com/questions/7993546 */ 
public class FilterTest { 

    private static TableRowSorter<TableModel> sorter; 
    private static RowFilter<TableModel, Integer> dFilter; 
    private static RowFilter<TableModel, Integer> fFilter; 
    private static boolean b; 

    public static void main(String[] args) { 
     TableModel model = new TableModel(); 
     JTable table = new JTable(model); 
     sorter = new TableRowSorter<TableModel>(model); 
     dFilter = RowFilter.numberFilter(ComparisonType.AFTER, 1d, 0); 
     fFilter = RowFilter.numberFilter(ComparisonType.AFTER, 1f, 0); 
     sorter.setRowFilter(dFilter); 
     table.setRowSorter(sorter); 
     JScrollPane scrollPane = new JScrollPane(table); 
     table.setPreferredScrollableViewportSize(new Dimension(320, 240)); 

     JFrame f = new JFrame("Test"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(scrollPane, BorderLayout.CENTER); 
     f.add(new JToggleButton(new AbstractAction("Toggle") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       b = !b; 
       if (b) { 
        sorter.setRowFilter(fFilter); 
       } else { 
        sorter.setRowFilter(dFilter); 
       } 
      } 
     }), BorderLayout.SOUTH); 

     f.pack(); 
     f.setVisible(true); 
    } 

    private static class TableModel extends AbstractTableModel { 

     private static final int ROWS = 16; 
     private static final int COLS = 4; 
     private Double[][] matrix = new Double[ROWS][COLS]; 

     public TableModel() { 
      double v = 0; 
      for (Object[] row : matrix) { 
       Arrays.fill(row, Double.valueOf(v += 0.25)); 
      } 
     } 

     @Override 
     public int getRowCount() { 
      return ROWS; 
     } 

     @Override 
     public int getColumnCount() { 
      return COLS; 
     } 

     @Override 
     public Object getValueAt(int row, int col) { 
      return matrix[row][col]; 
     } 

     @Override 
     public Class<?> getColumnClass(int col) { 
      return Number.class; 
     } 
    } 
} 
+0

pour l'affichage de sscce +1 – mKorbel

+0

ouais, c'est l'effet qu'un client d'un client a détecté BTW, non lié à la boîte ou non, juste pour clarifier. Merci pour le résultat! – kleopatra

Questions connexes