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
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.
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
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.
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 !!!
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.
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!
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