Newsgroup: it.comp.java
Titolo: Filtro su JTable minuscolo maiuscolo

Ciao a tutti,
ho una Jtable con colonne di vario tipo: stringhe, boolean, date,
numeri.
Usando TableRowSorter sono riuscito ad eseguire il filtro su tutte le
colonne.
Il problema rimane solo per il maiuscolo / minuscolo.
Se ho due recordo con la stringa "Casa" e "casa" non riesco a
visualizzare correttamente i record se scrivo "CASA".
il codice che non funziona è il seguente:
this.jTable1.setModel(model);
        Comparator<Short> intComp = new Comparator<Short>() {
            public int compare(Short o1, Short o2) {
                String x = o1.toString().toUpperCase();
                String y = o2.toString().toUpperCase();
                return x.compareTo(y);
            }
        };
        sorter = new TableRowSorter<TableModel>(model);
        sorter.setComparator(3, intComp);
        this.jTable1.setRowSorter(sorter);
qualcuno ha suggerimenti?
Grazie

 Grazie
C'e' sicuramente qualcosa che mi sfugge:
nella quarta colonna (quella con indice 3) ci sono davvero degli Short?
In tal caso il comparator Comparator<Short> e' inutile, in quanto Short 
gia' implementa Comparable<Short> e di fatto 
Short.toString().toUpperCase(); restituisce la stessa stringa di 
Short.toString() in quanto i numeri sono uguali sia in maiuscolo che in 
maiuscolo. :-)
Mi sarei aspettato che se "Casa", "casa" e "CASA" dovessero comparire 
nella quarta colonna e dovendo rendere il sort insensibile al case, tu 
avessi iniettato un comparator basato su String e non su Short, ovvero:
Comparator<String> intComp = new Comparator<String >() {
   public int compare(String o1, String o2) {
	if (o1 == null && o2 == null) return 0;
	else if (o1 != null && o2 == null) return 1;
	else if (o1 == null && o2 != null) return -1;
	else return o1.toUpperCase().compareTo(o2.toUpperCase());
   }
};
dove il valore null viene arbitrariamente considerato inferiore a 
qualsiasi altro valore ed identico ad un altro null.

 > il codice che non funziona è il seguente:

Non funziona. Ho provato con una JTable composta da 6 colonne generate
dalla lettura del database con l'istruzione
row.add(rs.getObject(i));
1) numerico
2) stringa
3) stringa
4) boolean
5) numerico
6) data
eseguendo il filtro funziona perfettamente su tutte le colonne. Tranne
che per il fatto che rimane sensibile alla maiuscola / minuscola.
Il codice è esattamente questo:
this.jTable1.setModel(model);
        Comparator<String> intComp = new Comparator<String>() {
            public int compare(String o1, String o2) {
                if (o1 == null && o2 == null) {
                    return 0;
                } else if (o1 != null && o2 == null) {
                    return 1;
                } else if (o1 == null && o2 != null) {
                    return -1;
                } else {
                    return o1.toUpperCase().compareTo(o2.toUpperCase
());
                }
            }
        };
        sorter = new TableRowSorter<TableModel>(model);
        sorter.setComparator(2, intComp);
        this.jTable1.setRowSorter(sorter);
Non riesco ad individuare il problema.
Grazie

 
Probabilmente c'e' qualcosa nel model. Ho fatto questa prova:
import java.util.*;
import javax.swing.*;
public class Tabella extends JFrame {
	public static String[] colNames = {
		"1) numerico","2) stringa", "3) stringa",
		"4) boolean", "5) numerico", "6) data"
	};
	public static Object[][] cols = {
		{1, "uno", "casa", true, 10, new Date()},
		{2, "due", "Casa", false, 20, new Date()},
		{3, "tre", "CASA", true, 30, new Date()},
		{4, "quattro", "pippo", false, 40, new Date()},
		{5, "cinque", "albero", true, 50, new Date()},
		{6, "sei", "paterino", false, 60, new Date()},
		{7, "sette", "caserma", true, 70, new Date()},
		{8, "otto", "casaccia", false, 80, new Date()},
		{9, "nove", "Casaccia", true, 90, new Date()}
	};
	public static void main(String[] args) {
		Tabella t = new Tabella();
		t.initialize();
		t.setVisible(true);
		t.pack();
	}
	public void initialize() {
		JTable tab = new JTable(cols, colNames);
		JPanel p = new JPanel();
		p.add(new JScrollPane(tab));
		add(p);
		tab.setAutoCreateRowSorter(true);
	}
}
sortando la colonna 3), l'ordine della prima colonna diventa 5 1 2 3 8 9 
7 6 4 quindi in ordine alfabetico crescente case insensitive.
Sinceramente non me ne ero mai accorto, ma sembra che l'ordinamento di 
String sia giï¿œ case insensitive per default.

 String sia già case insensitive per default.
Forse sono io che mi sono espresso male, il sort funziona anche a me.
In pratica ho costruito una JDialog che contiene una Jtable ed un
JTextField.
Quando inserisco una stringa nel JTextField vorrei ottenere un filtro
su tutti i record della JTable.
A parte il problema minuscolo / maiuscolo funziona tutto alla
meraviglia. Mi esegue un filtro su tutte le colonne e su tutti i
record, stupendo.
Peccato che sia case sensitive (mi sembra che si dica così).
Quando inserisco una stringa tipo "aso" mi vengono mostrati i record
- Naso
- Vaso
- Travaso
Se invece scrivo "vaso" il filtro mi mostra solo
- Travaso
io vorrei vedere
- Vaso
- Travaso
Ora sì che sono stato chiaro !!!


Ho capito dov'è il problema ma non so come risolverlo. Se aggiungo una
riga per stampare il ciclo Comparator non stampa nulla.
his.jTable1.setModel(model);
        Comparator<String> intComp = new Comparator<String>() {
            public int compare(String o1, String o2) {
                if (o1 == null && o2 == null) {
                    return 0;
                } else if (o1 != null && o2 == null) {
                    return 1;
                } else if (o1 == null && o2 != null) {
                    return -1;
                } else {
                    System.out.println(o1); // <-------------------
                    return o1.toUpperCase().compareTo(o2.toUpperCase
());
                }
            }
        };
        sorter = new TableRowSorter<TableModel>(model);
        sorter.setComparator(2, intComp);
        this.jTable1.setRowSorter(sorter);
        String expr = this.testoFiltro.getText();
        sorter.setRowFilter(RowFilter.regexFilter(expr));
quindi il cliclo non viene mai richiamato. Bel mistero !!!

 quindi il cliclo non viene mai richiamato. Bel mistero !!!
Neanche con sorter.sort(); ?
Il comparator del TableRowSorter direi che intervenga solo durante il sort.
E comunque non vedo come tale comparator possa essere legato al filtro. 
Come l'hai costruito?

 Come l'hai costruito?
Come ho costruito il tutto. Semplice:
il JDialog contiene:
- una JTable con i record tabellari;
- una JTextField per inserire la stringa da utilizzare per il filtro;
- un JButton per eseguire il filtro;
- un JButton per eliminare il filtro.
Quando premo il JButton attivo il seguente evento
private void buttonFiltroActionPerformed(java.awt.event.ActionEvent
evt) {
        Comparator<String> intComp = new Comparator<String>()  {
            public int compare(String o1, String o2) {
                return o1.toUpperCase().compareTo(o2.toUpperCase());
            }
        };
        sorter = new TableRowSorter<TableModel>(model);
        sorter.setComparator(1, intComp);
        this.jTable1.setRowSorter(sorter);
        String expr = this.testoFiltro.getText();
        sorter.setRowFilter(RowFilter.regexFilter(expr));
        sorter.setSortKeys(null);
    }
Funziona tutto alla meraviglia se inserisco un numero, per esempio se
scrivo "12" mi visualizza i record che contengono il "12" sia
all'interno di una data (12/06/2009) sia all'interno di un importo
(3612,00). Se invece la stringa contiene caratteri alfabetici mi
distingue la maiuscola dalla minuscola. Quindi "casa" e "Casa" danno
risultati diversi.

>> Ho capito dov'ï¿œ il problema ma non so come risolverlo. Se aggiungo una

Capisco. Allora, direi che creare un sorter no serva, se la tabella ne 
ha gia' uno basta usare il getter. Inoltre se usi un filtro regex, 
l'argomento per crearlo dev'essere una regular-expression, nel tuo caso:
String expr = this.testoFiltro.getText();
expr e' la regular expression 'banale' ovvero la regular-expression che 
selezionea solo il testo contenuto nel JTextField e quindi e' per forza 
di cose case-sensitive.
Quindi se non vuoi compilarti a mano la regex, direi che la maniera piu' 
semplice, ma non sono sicurissimo dato che non e' esattamente il mio 
ambito, sia quello di usare la Classe Pattern cosï¿œ:
Pattern p = Pattern.compile(
	this.testoFiltro.getText(),
	Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
e creati un tuo filtro utilizzando questo pattern, fatto come 
regexFilter, ad esempio:
class RegexFilterCaseIns extends GeneralFilter {
   private Matcher matcher;
   public RegexFilterCaseIns (String text, int[] columns) {
     super(columns);
     if (text== null) throw new NullPointerException("text");
     matcher = Pattern.compile(text,
	Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher("");
   }
   protected boolean include(
	Entry<? extends Object,? extends Object> value, int index) {
     matcher.reset(value.getStringValue(index));
     return matcher.find();
   }
}
tanto per avere un'idea di cosa sia fatta una regular-expression, prova 
a guardare 
http://oreilly.com/catalog/9780596002893/
 oppure 
http://www.unicode.org/reports/tr18/
 .
Capisco ed ammetto che le regular-expression siano comode, ma la 
sintassi e' parecchio fuori dal mio modo di vedere per cui se posso le 
evito!

>> Ho capito dov'ï¿œ il problema ma non so come risolverlo. Se aggiungo una



 evito!
Ti ringrazio, come al solito sei gentilissimo.
Dovrò studiarci un po' però perché il mio livello di java è ancora
troppo acerbo per capire tutto quello che ho letto.
Grazie