Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Renault 5 elettrica al giudizio definitivo: solo stupore iniziale o premi meritati?
Renault 5 elettrica al giudizio definitivo: solo stupore iniziale o premi meritati?
Dopo più di un anno dal primo test drive ci siamo rimessi al volante della Renault 5 E-Tech Electric, questa volta utilizzandola come prima auto per circa due settimane. Scoprite con noi se il progetto convince ancora
HONOR CHOICE Projector Air Pro: piccolo, portatile e con Netflix
HONOR CHOICE Projector Air Pro: piccolo, portatile e con Netflix
Un proiettore economico, che fa della portabilità e immediatezza i suoi punti di forza. Adatto per una camera da letto o per la casa vacanze, è basato su sistema proprietario Linux ma offre piena compatibilità ufficiale a Netflix
ASUS ProArt GoPro Edition è il notebook compatto per chi crea
ASUS ProArt GoPro Edition è il notebook compatto per chi crea
Un notebook sviluppato in collaborazione con GoPro ma che risponde al meglio alle necessità di tutti coloro che creano contenuti video: robustezza, design, potenza di calcolo e funzionalità si abbinano al meglio tra di loro, pur se a prezzo di un costo elevato per via della tanta memoria onboard
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 23-04-2006, 15:45   #1
guldo76
Senior Member
 
L'Avatar di guldo76
 
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
guldo76 è offline   Rispondi citando il messaggio o parte di esso
Old 24-04-2006, 13:25   #2
guldo76
Senior Member
 
L'Avatar di guldo76
 
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
guldo76 è offline   Rispondi citando il messaggio o parte di esso
Old 24-04-2006, 13:42   #3
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
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 .
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 24-04-2006, 20:14   #4
guldo76
Senior Member
 
L'Avatar di guldo76
 
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());
	}
	// [...]
    }
}
Poi nel main istanzio un ArrayList e lo passo al costruttore di LANFrame.
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
guldo76 è offline   Rispondi citando il messaggio o parte di esso
Old 25-04-2006, 11:42   #5
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
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);
    }
}
e generare una "normale" tabella:

Codice:
ConnTableModel model = new ConnTableModel(...);
LANTable table = new LANTable(model);
Le viste dipendono dalla dichiarazione di un modello ma non dalla sua definizione. Per chiarezza, itendo per dichiarazione TableModel e per definizione un qualsiasi oggetto compatibile con TableModel (ad esempio proprio ConnTableModel).

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 ).
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 25-04-2006, 17:08   #6
guldo76
Senior Member
 
L'Avatar di guldo76
 
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
Quote:
Originariamente inviato da PGI-Bis
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.
Ciao.
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;
    }
[...]
}
E poi quando la istanzio provo subito a "filtrarla":
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);
Cosa c'è di sbagliato?

Grazie
guldo76 è offline   Rispondi citando il messaggio o parte di esso
Old 26-04-2006, 13:02   #7
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
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);
    }
}
Sono anch'io dell'idea che il filtro deva tener traccia delle delle righe valide: una specie di mappa tra gli indici delle righe visibili ed il loro corrispondente del modello.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 26-04-2006, 21:13   #8
guldo76
Senior Member
 
L'Avatar di guldo76
 
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;
    }
così il metodo getValueAt restitusce un null nel caso della riga di indice 1.
Questo genera una NullPointerException.

Come devo implementare allora questo metodo, per fargli "saltare" la riga in questione?

Grazie
guldo76 è offline   Rispondi citando il messaggio o parte di esso
Old 27-04-2006, 12:06   #9
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
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);
}
Quel "model.getValueAt(realRow, column)" deve essere inteso nel senso di "il valore che sarebbe stato restituito se non fosse stato applicato alcun filtro".
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 28-04-2006, 21:53   #10
guldo76
Senior Member
 
L'Avatar di guldo76
 
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;
    }
Ora ho problemi con la grafica
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
guldo76 è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2006, 02:21   #11
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
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.
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 29-04-2006, 10:51   #12
guldo76
Senior Member
 
L'Avatar di guldo76
 
Iscritto dal: Nov 2002
Città: Morio Cho
Messaggi: 2598
Fantastico!
Non so come ringraziarti!
guldo76 è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Renault 5 elettrica al giudizio definitivo: solo stupore iniziale o premi meritati? Renault 5 elettrica al giudizio definitivo: solo...
HONOR CHOICE Projector Air Pro: piccolo, portatile e con Netflix HONOR CHOICE Projector Air Pro: piccolo, portati...
ASUS ProArt GoPro Edition è il notebook compatto per chi crea ASUS ProArt GoPro Edition è il notebook c...
Fable e Sol a confronto: due cartoni animati creati su un PC con RTX 3090 Fable e Sol a confronto: due cartoni animati cre...
Il tablet rugged leggero e sottile: Lenovo ThinkTab X11 offre resistenza, doppia USB-C e batteria rimovibile Il tablet rugged leggero e sottile: Lenovo Think...
TSMC accelera sui 1,4 nanometri: produzi...
Razer compra StreamElements: cambia tutt...
Il Task Manager di Windows arriva su Mac...
Sony: PS5 resta più conveniente d...
Ubisoft spegne uno dei suoi esperimenti ...
Garante Privacy: multa da 9,5 milioni di...
Windows 11, Microsoft promette un sistem...
Windows 11, l'ultima build sperimentale ...
YouTube cancella i canali ASMR più...
Valgono miliardi, ma non pubblicano rice...
ROG Falchion Ace 75 HE: ASUS fa sul seri...
Google rilascia il primo teaser dei Pixe...
Attenti a queste TV Box: a TV spento si ...
Radeon RX 9050: arriva il primo confront...
L'AI Act più severo slitta al 202...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 01:31.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v