Ciao a tutti,
volevo chiedervi un piccolo (forse) aiuto. Devo consegnare un progetto a breve e sto sbattendo la testa al muro perché alcune cose non le ho capite proprio. Il professore e le sue direttive ambigue (e la sua scarsa reperibilità per chiarimenti) non contribuiscono.

PREMESSA: non sto chiedendo la soluzione totale del esercizio

La specifica del progetto (per una buona parte risolto, spero) sono:


Il gruppo dovrà realizzare una applicazione swing, con classe avviabile ClientGrafico.
[..]
Il client ha lo scopo di visualizzare, modificare e utilizzare i contenuti forniti dalla libreria.
[..]
Il gruppo dovrà realizzare una applicazione swing, con classe avviabile ClientGrafico.

La classe concreta TabellaDati rappresenta una tabella, che avrà la prima riga vuota ed editabile. Modificando la prima riga (tramite i metodi richiamati dal Client) il contenuto della tabella potrà variare. Esempio: se ho i risultati di una giornata calcistica, e scrivo Milan nella prima cella, potrebbe mostrarmi solo la riga relativa al risultato del Milan.



codice:
import javax.swing.event.ChangeListener;
import javax.swing.table.TableModel;

public abstract class AbstractTabellaDati implements TableModel 
{
	/* Da utilizzare per creare oggetti (no costruttori) */
	public static AbstractTabellaDati getTabellaDati() 
	{
		throw new UnsupportedOperationException();
	};

	/** 
	 * Restituisce true se la cella in posizione (rowIndex,columnIndex) è modificabile. 
	 * Deve restituire sempre true per tutte le celle con rowIndex == 0 
	 */
	abstract public boolean isCellEditable(int rowIndex, int columnIndex);
	
	/** 
	 * Implementazione da documentazione in TableModel. Inoltre, ogni volta che viene chiamato, 
	 * anche su celle non editabili, deve verificare che non siano stati modificati i dati nella 
	 * sorgente dati (dipendente da progetto) ed eventualmente gestire il Listener per informare il 
	 * client dell'aggiornamento dei dati.In questo modo sul client ci saranno tutti i dati aggiornati 
	 * ogni volta che si prova a modificare una cella con setValueAt.
	 */
	abstract public void setValueAt(Object aValue, int rowIndex, int columnIndex);
}
Quel che ho fatto, è stato creare un TabellaDati così (molti metodi sono implementazioni "standard" dei metodi di TableModel)

codice:
import java.util.ArrayList;

import javax.swing.event.TableModelListener;

public class TabellaDati extends AbstractTabellaDati
{
	private static TabellaDati istanza = null;
	
	private static ArrayList<Squadra> serieA = null;
	private static String filter_col0 = null;
	private static int[] order_int = {0,0,0,0,0,0,0,0,0};
	
	private static String[] columnNames = {"Squadra", "Posizione", "Punti", "Giocate", "Vittorie", "Pareggi", 
		"Sconfitte", "Reti Segnate", "Reti Subite", "Differenza Reti"};
	
	private static ArrayList<TableModelListener> listeners = new ArrayList<TableModelListener>();

	private TabellaDati(){}
	
	public static AbstractTabellaDati getTabellaDati() 
	{
		if(istanza == null)
		{
			TabellaDati.istanza = new TabellaDati();
			TabellaDati.serieA = SerieA.getSerieA();
		}
		return istanza;
	}
	
	@Override
	public void addTableModelListener(TableModelListener arg0) 
	{
		listeners.add(arg0);
	}

	@Override
	public Class<?> getColumnClass(int arg0) 
	{
		switch(arg0)
		{
			case 0: 
				return String.class; 
				
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 8:
			case 9:
				return Integer.class;
			
			default:
				return Object.class;
		}
	}

	@Override
	public int getColumnCount() 
	{
		return columnNames.length;
	}

	@Override
	public String getColumnName(int arg0) 
	{
		return columnNames[arg0];
	}

	@Override
	public int getRowCount() 
	{
		return serieA.size() + 1;
	}

	@Override
	/**
	 * Questo metodo, data una cella restituisce l'oggetto che la occupa in quel dato momento. La prima riga è
	 * speciale, essendo quella editabile e che quindi contiene i valori inseriti dall'utente, e viene quindi
	 * trattata a parte.
	 * @param int arg0 La riga della cella
	 * @param int arg1 La colonna della cella
	 */
	public Object getValueAt(int arg0, int arg1) 
	{
		if(arg0 == 0)
		{
			if(arg1 == 0)
			{
				return TabellaDati.filter_col0;
			}
			else
			{
				return TabellaDati.order_int[arg1-1];
			}
		}
		else
		{
			return TabellaDati.serieA.get(arg0-1).getColonna(arg1);
		}
	}

	@Override
	public void removeTableModelListener(TableModelListener arg0) 
	{
		listeners.remove(arg0);
	}

	@Override
	/**
	 * Metodo per rendere permanenti le modifiche ad una cella
	 */
	public void setValueAt(Object arg0, int arg1, int arg2) 
	{
		if(isCellEditable(arg1, arg2))
		{
			if(arg2 == 0)
			{
				filter_col0 = (String) arg0;
				serieA = SerieA.getSquadrePerFiltro((String) arg0);
			}
			else
			{
				order_int[arg2-1] = (int) arg1;
			}
		}
		
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) 
	{
		if(rowIndex == 0)
		{
			return true;
		}
		
		return false;
	}

}
Le classi SerieA e Persona hanno metodi che funzionano e che non toccano la tabella, ma solo la struttura dati. Cioè leggono i dati da internet ed eventualmente li filtra.

Il mio progetto dovrebbe fare un filtro sulla prima colonna, a seconda del parametro string che gli si scrive. Gli altri valori sono int e ci inventeremo dei filtri anche per quello.

Quello che mi chiedo io è: ho visto in altri esempi in giro che per rendere permanenti delle modifiche alla tabella si usano i metodi fireCellTableUpdate e simili che sono di AbstractTableModel ma noi non possiamo usarli, perché Java non ha ereditarietà multipla... quindi, posto che il programma così scritto riesce a leggere i dati da internet e a mostrarmi una tabella con i dati giusti, con una prima riga vuota ed editabile, come faccio a imporgli un refresh dei dati? Non ho proprio capito come dovrei usare i TableModelListener e, soprattutto, e perché lui mi importa l'interfaccia ChangeListener.

Grazie a tutti quelli che risponderanno, mi rendo conto che è un post lungo e noioso...