Ligação entre AbstractTableModel e LinkedList

To reescrevendo uma pequena aplicação em swing com o objetivo de dar uma treinada em POO e no modelo MVC.
Antes o código tinha todas as JTable com DefaultTableModel, então resolvi montar meus próprios TableModel e procurei alguns exemplos na internet, depois de um tempo “consegui montar” e fazer funcionar e percebi que o método addRow não era herdado da AbstractTableModel, acontece que quando eu puxo os dados do banco, eu adiciono eles na LinkedList mas diferente de como eu fazia antes(com a DefaultTableModel), não precisei usar o addRow pra ESCREVER as linhas na minha JTable, ela só pegou os dados direto da LinkedList, e quero entender como isso aconteceu.

TableModel:

package m;

import java.util.LinkedList;
import javax.swing.table.AbstractTableModel;

public class StudentTableModel extends AbstractTableModel {

	
	private static final long serialVersionUID = 1L;
	private final String[] columns = {"Code", "Name", "Phone"};
	private LinkedList<Student> list;
	private StudentDAO cmd = new StudentDAO();
	
	public StudentTableModel()
	{
		 list = new LinkedList<Student>();
		 refreshStudents();
		 
	}
	
	/*public boolean addStudent(Student student)
	{
		list.add(student);
		fireteibodataxenged();
		return true;
	}
	*/
	
	// Método que usa a instância da minha DAO pra adicionar os dados SOMENTE na lista
	public boolean refreshStudents(){
		
		cmd.refresh(list);
		fireTableDataChanged();
		return true;
	}
	
	public int getColumnCount() {
		return columns.length;
	}

	public int getRowCount() {
		return list.size();
	}

	public Object getValueAt(int row, int column) {
		
			switch(column)
			{
			
			case 0 : return list.get(row).getCod();
			
			case 1 : return list.get(row).getName();
			
			case 2 : return list.get(row).getPhone();
			
			}
			
			return null;
		
	}

	public Class<?> getColumnClass(int column)
	{
		switch(column)
		{
		case 0 : return Integer.class;
		
		case 1 : return String.class;
		
		case 2 : return Integer.class;
		
		default: return null;
		}
	}
	
	public boolean isCellEditable(int row, int column)
	{
		return false;
	}
}

DAO:

package m;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;

public class StudentDAO  {

	private Connection connection;
	private Statement statement;
	private ResultSet resultset;
	
	public StudentDAO()
	{
		connection = new MyConnection().getConnection();

	}
	
	
	public boolean register(Student student){
		
		try {
			
			PreparedStatement pStatement = connection.prepareStatement("INSERT INTO `db_kanri`.`students` (`cod`, `name`, `rg`, `idade`, `phone`, `gender`, `picture`) VALUES ('', '?', '?', '?', '?', '?', '?');");
			
			pStatement.setString(2, student.getName());
			pStatement.setString(3, student.getRg());
			pStatement.setInt(4, student.getAge());
			pStatement.setString(5, student.getPhone());
			pStatement.setBoolean(6, student.isGender());
			pStatement.setString(7, student.getPicture());
			pStatement.executeUpdate("");
			
			pStatement.close();
			
			return true;
			
		} catch (SQLException e) {
			
			e.printStackTrace();
			
			return false;
		}
		finally{
			
		}
		
	}
	
	// Método que retorna
	public boolean refresh(LinkedList<Student> list)
	{
		 try {
			 
		 statement = connection.createStatement();
		 resultset = statement.executeQuery("SELECT * FROM STUDENTS");
		
		 while(resultset.next())
		 {
			 Student student = new Student();
			 student.setCod(resultset.getInt("cod"));
			 student.setName(resultset.getString("name"));
			 student.setRg(resultset.getString("rg"));
			 student.setAge(resultset.getInt("age"));
			 student.setGender(resultset.getBoolean("gender"));
			 student.setPhone(resultset.getString("phone"));
			 student.setPicture(resultset.getString("picture"));
			 list.add(student);
			 
			
		 }
		 
		  close();
		 
		  return true;
			
		} 
		 catch (SQLException e) {
			 
			e.printStackTrace();
			return false;
			
		}
		
	}
	
	private void close(){
		
		try {
			
			statement.close();
			resultset.close();
			
		} catch (SQLException e) {
			
			e.printStackTrace();
		}
		
	}
	
	
} 

View + Pergunta:

package v;

import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;
import javax.swing.JTable;

import m.StudentTableModel;

public class Students extends JInternalFrame {

	
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JTable table;

	public Students() {
		setClosable(true);
		
		setTitle("Students");
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(100, 100, 800, 600);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(10, 11, 604, 549);
		contentPane.add(scrollPane);
		
		StudentTableModel model = new StudentTableModel();
		table = new JTable();
		// Eu to setando a model e só, onde tá escrito que  a JTable tem que pegar os dados da minha LinkedList?
		table.setModel(model);
		table.getColumnModel().getColumn(0).setHeaderValue("Code");
		table.getColumnModel().getColumn(1).setHeaderValue("Name");
		table.getColumnModel().getColumn(2).setHeaderValue("Phone");
		scrollPane.setViewportView(table);
	}
}
1 curtida

Essa é a grande vantagem de não utilizar DefaultTableModel, você implementou um TableModel próprio que apenas renderiza uma lista, sem se preocupar em quem popula esta lista. :slight_smile:
É assim que deve ser!

Se você não sabe como sua lista é populada, de acordo com o seu código isso é feito no método abaixo:

public boolean refreshStudents(){
	cmd.refresh(list);       // aqui provavelmente seu DAO manipula a lista inserindo elementos
	fireTableDataChanged();  // aqui você manda a JTable se redesenhar, de forma que irá renderizar os elementos de sua lista
	return true;
}
2 curtidas

Olá Staroski, obrigado pela resposta, depois de ficar lendo meu código por algumas horas, consegui entender o que estava acontecendo, eu sabia sim como minha lista era populada, só não entendia como isso chegava na JTable.

StudentTableModel model = new StudentTableModel();
table = new JTable();

Eu to setando a model e só, onde tá escrito que a JTable tem que pegar os dados da minha LinkedList?

table.setModel(model);

Depois de um tempo analisando entendi que quando minha TableModel era instânciada, os dados eram passados automaticamente através do método getValueAt que percorria toda a LinkedList pegando valor por valor.

public Object getValueAt(int row, int column)
{	
	switch(column)
	{			
		case 0 : return list.get(row).getCod();			
		case 1 : return list.get(row).getName();			
		case 2 : return list.get(row).getPhone();			
	}
	return null;		
}
2 curtidas

Isso mesmo, a JTable invoca os métodos do TableModel sob demanda, então, quando ela vai renderizar o conteúdo de uma célula, ela chama o método getValueAt(linha, coluna).
Se você observar, o Swing utiliza MVC ao extremo, então a maioria dos componentes possuem interfaces que servem de modelo para o componente.

1 curtida