|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
|
[java] filtrare tabella
Ciao
Sto cercando di capire come si potrebbe fare per filtrare una tabella in java (swing). Cioè: ho un oggetto JTable, creato in base a un arraylist; vorrei filtrare il contenuto del JTable in base alla selezione effettuata in un JComboBox esterno. In base alla selezione effettuata nel JComboBox, andrebbero tolte dalla JTable le righe corrispondenti. Si può fare? Ho visto che nella classe JTable è previsto il sort della tabella, ma del filter non ho trovato traccia... L'unica cosa che mi è venuta in mente è distruggere e ricreare la tabella tutte le volte, modificando la fonte dati; ma è terribile... Grazie
__________________
Sono GULDO, non Guido! Cioè, certo che guido... Bé, insomma, avete capito ![]() Linux 2.6.26|Debian|Debian@Hwupgrade|Debian Clan|Solo Puffin ti darà forza e grinta a volontà! NERD rank 62|Milla Jovovich|大事な物はいつも形の無い物だけ Sito e Forum sul Giappone|La mia libreria su aNobii |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
|
__________________
Sono GULDO, non Guido! Cioè, certo che guido... Bé, insomma, avete capito ![]() Linux 2.6.26|Debian|Debian@Hwupgrade|Debian Clan|Solo Puffin ti darà forza e grinta a volontà! NERD rank 62|Milla Jovovich|大事な物はいつも形の無い物だけ Sito e Forum sul Giappone|La mia libreria su aNobii |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Funziona anche cambiando il modello ma, in accordo all'architettura MVC (o SMA), dovresti agire sulla vista (JTable).
JTable ha tre metodi ad hoc: getRowCount() getColumnCount() getValueAt(int row, int col) Per definizione questi metodi si rifanno al TableModel. La tabella "standard" mostra tante righe e tante colonne quante sono quello nel modello e restituisce i valori corrispondenti alle righe del modello. Tutto ciò di cui hai bisogno è determinare, a seguito dell'operazione di filtraggio, quali righe del modello siano da scartare. Restituirai quindi attraverso getRowCount un numero di righe pari al numero di righe nel modello meno quelle scartate dal filtro. Concordemente farai sì che il metodo getValueAt tenga conto della "sparizione" di queste righe. E il gioco è fatto |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
|
Grazie mille della risposta
Però ho ancora un po' di problemi... Mi da più di una: Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException Quello che ho fatto è grossomodo questo: Codice:
public class LANTable extends JTable {
private ArrayList _righeOk = new ArrayList();
private ArrayList _source;
public LANTable(ArrayList connList) {
super();
this.setModel(new ConnTableModel(connList));
// [...]
_righeOk.clear();
for (int i = 0; i < _source.size(); i++)
_righeOk.add(new Integer(i));
}
public void Filter(String nomeRete) {
Iterator iter = _source.iterator();
int i = 0;
_righeOk.clear();
while (iter.hasNext()) {
LANConnection x = (LANConnection) iter.next();
if (x.get(x.getKeysArray()[0]).toString().equals(nomeRete))
_righeOk.add(new Integer(i));
}
}
class ConnTableModel extends AbstractTableModel {
public ConnTableModel(ArrayList connList) {
_source = connList;
}
// [...]
public int getRowCount() {
return _righeOk.size();
}
public Object getValueAt(int arg0, int arg1) {
Object risultato = null;
if (_righeOk.contains(new Integer(arg0))) {
LANConnection x = (LANConnection) _source.get(arg0);
risultato = x.get(x.getKeysArray()[arg1]);
}
return risultato;
}
// [...]
}
}
public class LANFrame extends JFrame {
public LANFrame(ArrayList list) {
super("Connessioni LAN");
final ArrayList myList = list;
// [...]
final LANTable myTab = new LANTable(myList);
final JComboBox jcmb = new JComboBox();
jcmb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
myTab.Filter(jcmb.getSelectedItem().toString());
}
});
TreeSet ts = new TreeSet();
String[] k = ((LANConnection)myList.get(0)).getKeysArray();
for (int i = 0; i < myList.size(); i++) {
ts.add(((LANConnection)myList.get(i)).get(k[0]));
}
Iterator iter = ts.iterator();
while (iter.hasNext()) {
jcmb.addItem(iter.next());
}
// [...]
}
}
Dov'è che sbaglio? Inoltre ho un po' di problemi a ricreare la tabella rileggendo l'arraylist da un file (serialized); è corretto valorizzare un attributo di una classe in una sua classe interna? Cioè, nel mio esempio, è corretto valorizzare "_source" all'interno del costruttore della classe "ConnTableModel"? Grazie
__________________
Sono GULDO, non Guido! Cioè, certo che guido... Bé, insomma, avete capito ![]() Linux 2.6.26|Debian|Debian@Hwupgrade|Debian Clan|Solo Puffin ti darà forza e grinta a volontà! NERD rank 62|Milla Jovovich|大事な物はいつも形の無い物だけ Sito e Forum sul Giappone|La mia libreria su aNobii |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
E' anche possibile che esista un caso in cui una classe interna possa assegnare un valore ad un campo della classe che la contiene ma nel caso di specie è bizzarro.
Sembrerebbe più coerente definire il modello ConnTableModel come tipo primario, dire: Codice:
public class LANTable ... {
...
public LANTable(TableModel model) {
super(model);
}
}
Codice:
ConnTableModel model = new ConnTableModel(...); LANTable table = new LANTable(model); Per l'eccezione NullPointerException occorre controllare la traccia stampata sulla console. Ad occhio non mi sembra di aver visto puntatori a null nel codice (ma non sono mai stato un'aquila |
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
|
Quote:
L'ho rivisto praticamente daccapo, seguendo le tue indicazioni successive, ma questo ancora non mi riesce. Evidentemente come lo faccio io non va bene Per ora è così: Codice:
public class LANTableModel extends AbstractTableModel{
private ArrayList<LANConnection> _source;
private ArrayList<Integer> _righeOk;
public LANTableModel(ArrayList<LANConnection> connList){
_source = connList;
_righeOk = new ArrayList<Integer>();
for(int i=0; i<_source.size(); i++)
_righeOk.add(new Integer(i));
}
public int getRowCount(){
return _righeOk.size();
}
public Object getValueAt(int row, int column){
Object risultato = null;
LANConnection x = null;
if(_righeOk.contains(new Integer(row))){
x = _source.get(row);
risultato = x.get(x.getKeysArray()[column]);
}
return risultato;
}
[...]
}
Codice:
LANTableModel model = new LANTableModel(connList); LANTable tab = new LANTable(model); JScrollPane scroll = new JScrollPane(tab); this.add(scroll); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); model.getRigheOk().remove(0); Grazie
__________________
Sono GULDO, non Guido! Cioè, certo che guido... Bé, insomma, avete capito ![]() Linux 2.6.26|Debian|Debian@Hwupgrade|Debian Clan|Solo Puffin ti darà forza e grinta a volontà! NERD rank 62|Milla Jovovich|大事な物はいつも形の無い物だけ Sito e Forum sul Giappone|La mia libreria su aNobii |
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Puoi benissimo applicare il filtro al modello (TableModel) ma quello che intendevo io era filtrare la vista: i dati restano quelli che sono, attraverso il filtro se ne vedono solo alcuni. Una cosa del genere:
Codice:
public interface FiltroTabella {
int getRowCount();
int getColumnCount();
Object getValueAt(int row, int col);
void apply(JTable t);
}
Codice:
public class TabellaFiltrabile extends JTable {
private FiltroTabella filtro;
public void setFiltro(FiltroTabella t) {
filtro = t;
if(filtro != null) filtro.apply(this);
}
public int getRowCount() {
return filtro == null ? super.getRowCount() : filtro.getRowCount();
}
public int getColumnCount() {
return filtro == null ? super.getColumnCount() : filtro.getColumnCount();
}
public Object getValueAt(int r, int c) {
return filtro == null ? super.getValueAt(r, c) : filtro.getValueAt(r, c);
}
}
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
|
Ti ringrazio molto della pazienza e della disponibilità; quello che mi proponi è interessante
Però c'è una cosa a monte che vorrei capire. Per il momento prendiamo per buono il mio sistema di scegliere le righe "buone" all'interno della classe TableModel; supponiamo che faccia così: Codice:
public LANTableModel(ArrayList<LANConnection> connList){
_source = connList;
_righeOk = new ArrayList<Integer>();
for(int i=0; i<_source.size(); i++){
if(i != 1) // NE ESCLUDO UNA DI PROPOSITO
_righeOk.add(new Integer(i));
}
}
// [...]
public int getRowCount(){
return _righeOk.size();
}
public Object getValueAt(int row, int column){
Object risultato = null;
LANConnection x = null;
if(_righeOk.contains(new Integer(row))){
x = _source.get(row);
risultato = x.get(x.getKeysArray()[column]);
}
return risultato;
}
Questo genera una NullPointerException. Come devo implementare allora questo metodo, per fargli "saltare" la riga in questione? Grazie
__________________
Sono GULDO, non Guido! Cioè, certo che guido... Bé, insomma, avete capito ![]() Linux 2.6.26|Debian|Debian@Hwupgrade|Debian Clan|Solo Puffin ti darà forza e grinta a volontà! NERD rank 62|Milla Jovovich|大事な物はいつも形の無い物だけ Sito e Forum sul Giappone|La mia libreria su aNobii |
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Forse abbiamo visto l'ArrayList in modo diverso
Quando scorri il modello per stabilire quali righe siano valide e quali no e immetti nell'ArrayList gli indici delle righe valide, l'ArrayList diventa una mappa di valori (X, Y = arrayList.get(N)), con X indice della riga richiesta dalla tabella e Y indice della riga "reale" nel modello. Il tuo getValueAt diviene pertanto: Codice:
public Object getValueAt(int row, int column) {
int realRow = _righeOk.get(row);
return model.getValueAt(realRow, column);
}
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
|
Grazie mille.
Quello che non capivo proprio era cosa restituire al posto della riga scartata dal filtro. Ho risolto così: Codice:
public Object getValueAt(int row, int column){
Object risultato = null;
LANConnection x = null;
if(row < _righeOk.size()){
row = Integer.valueOf(_righeOk.get(row));
}
x = _source.get(row);
risultato = x.get(x.getKeysArray()[column]);
return risultato;
}
La tabella è in un jscrollpane, che filtrandola sclera, rimane traccia dello spazio che avanza... Ho cercato di capire come funziona il repaint, ma non ci riesco... ![]() Sono andato prima per tentativi, con la tabella, il jscrollpane e il frame, poi ho cercato di leggere questo, ma non c'ho ricavato un granché... ![]() Grazie di nuovo
__________________
Sono GULDO, non Guido! Cioè, certo che guido... Bé, insomma, avete capito ![]() Linux 2.6.26|Debian|Debian@Hwupgrade|Debian Clan|Solo Puffin ti darà forza e grinta a volontà! NERD rank 62|Milla Jovovich|大事な物はいつも形の無い物だけ Sito e Forum sul Giappone|La mia libreria su aNobii |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
|
Dovresti invocare, dopo aver applicato il filtro, il metodo revalidate() della tabella (JTable) incriminata.
|
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
|
Fantastico!
Non so come ringraziarti!
__________________
Sono GULDO, non Guido! Cioè, certo che guido... Bé, insomma, avete capito ![]() Linux 2.6.26|Debian|Debian@Hwupgrade|Debian Clan|Solo Puffin ti darà forza e grinta a volontà! NERD rank 62|Milla Jovovich|大事な物はいつも形の無い物だけ Sito e Forum sul Giappone|La mia libreria su aNobii |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 01:31.





















