cabeçalho JTable

Bom dia!
Estou tendo um problema para exibir o cabecalho da minha JTable.

Quando instancio de dentro desta classe aparece o cabeçalho

import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;

public class MyTable extends JTable {
	private MyTableModel model;
	private static DBLayer db = DBLayer.getInstance();
	
	public MyTable(MyTableModel tableModel) {
		model = tableModel;
		setModel(model);
		setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		setFillsViewportHeight(true);
	}
	
	public void addRow(String table, String[] data) {
		db.addRow(table, data);
		model.addRow(data);
	}
	
	public void editRow(String table, int id, String[] data) {
		db.editRow(table, id, data);
		model.editRow(getSelectedRow(), data);
	}
	
	public static void main(String args[]) {
		JFrame f = new JFrame();
		db = DBLayer.getInstance();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Vector<Object[]> v = new Vector<Object[]>();
		v = db.getTableData("usuario");
		String[] s = db.getTableMetadata("usuario");
 		MyTableModel m = new MyTableModel(v, s);
		MyTable t = new MyTable(m);
		f.getContentPane().add(new JScrollPane(t));
		f.setVisible(true);
	}
}

mas quando instancio daqui não aparece.

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
import com.jgoodies.forms.layout.*;

public class Projeto extends JPanel{
	private JPanel panel;
	private MyTableModel model;
	private MyTable table;
	private MyMenu menu;
	private DBLayer db = DBLayer.getInstance();
	public Projeto() {
		setLayout(new BorderLayout());
		add(getPanel(), BorderLayout.CENTER);
	}
	
	public JPanel getPanel() {
		CellConstraints cc = new CellConstraints();
		FormLayout layout = new FormLayout(
				//columns
				"4dlu, " +
				"pref:grow, " +
				"4dlu",  
				//rows
				"4dlu, " +
				"pref, " +
				"2dlu, " +
				"fill:pref:grow, " +
				"4dlu"
		);
		panel = new JPanel(layout);
		panel.setBackground(Color.CYAN);
		
		JLabel title = new JLabel("Projeto");
		title.setFont(Constants.TITLE_FONT);
		
		Vector<Object[]> v = new Vector<Object[]>();
		v = db.getTableData("usuario");
		String[] s = db.getTableMetadata("usuario");
 		model = new MyTableModel(v, s);
		table = new MyTable(model);
		
		Handler handler = new Handler();
		table.addMouseListener(handler);
		
		panel.add(title, cc.xy(2, 2));
		panel.add(table, cc.xy(2, 4));

		return panel;
	}
	
	public static void main(String[] args) {
		JFrame f = new JFrame();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		f.getContentPane().add(new Projeto());
		f.setVisible(true);
		f.setExtendedState(JFrame.MAXIMIZED_BOTH);
	}
}

MyTableModel:

import java.util.Vector;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;


	public class MyTableModel extends AbstractTableModel {
		private Vector<Object[]> data = null;
		private String[] columns;

		public MyTableModel(Vector<Object[]> d, String[] c) {
			setRows(d);
			setColumns(c);
		}//construtor
		
		public Vector<Object[]> getRows() {
			return data;
		}
		
		public void setRows(Vector<Object[]> d) {
			data = d;
		}
		
		public String[] getColumns() {
			return columns;
		}
		
		public void setColumns(String[] c){
			columns = c;
		}
		
		public int getRowCount() {
			return getRows().size();
		}
		
		public int getColumnCount() {
			return getColumns().length;
		}
		
		public String getColumnName(int i) {
			return columns[i].toString();
		}

		public void setValueAt(Object value, int rowIndex, int columnIndex) {
			Object[] o = getRows().get(rowIndex);
			o[columnIndex] = value;
			fireTableCellUpdated(rowIndex, columnIndex);
		}

		public Object getValueAt(int rowIndex, int columnIndex) {
			Object[] o = (String[])getRows().get(rowIndex);
			return o[columnIndex];
		}
		
		public void addRow(String[] data) {
			getRows().add(data);
			int row = getRows().size()-1;
			fireTableRowsInserted(row,row);
			return;
		}
		
		public void editRow(int rowIndex, String[] values) {
			for(int i = 0; i < values.length; i++) {
				setValueAt(values, rowIndex, i);
			}
		}
	}

Alguém poderia me ajudar me dizendo porque aparece a tabela sem o cabeçalho?
Obrigado

O cabeçalho só aparece se a JTable estiver num JScrollPane.

Algumas dicas:

Implemente seu próprio TableModel:
Tutorial: www.informit.com/articles/article.aspx?p=332278

Não use Vector, use List.
Motivo: http://www.guj.com.br/posts/list/71926.java
Como usar: http://www.guj.com.br/posts/list/74068.java

Muito obrigado, ViniGodoy, realmente eu não tinha prestado atenção a este detalhe do JScrollPane…
Valeu a dica do ArrayList, ja substituí todos os Vectors.
Quanto ao TableModel, eu to implementando um próprio, é a ultima classe do tópico.

Forte abraço

E quanto a usar um Set?

O Set é uma boa se você:

  1. Não puder ter elementos duplicados E
  2. Não depender da ordenação ou índice dos elementos;

No caso do JTable, o segundo caso não bate. Você precisa dos índices das linhas para montar a tabela. Geralmente, é preferível se manter com um list (pelo menos dentro do TableModel).

Bom, eu to desenvolvendo uma aplicação usando hibernate. Já fiz a parte para usar os Set de relacionamentos para popular tabelas (Endereços, Telefones, coisas do gênero) e é meio trabalhoso quando tenho q fazer alguma alteraçao.
Nesse caso é melhor continuar usando Set ou mudar pra List, uma vez que não haverão entidades duplicadas?

[quote=Gobain]Bom, eu to desenvolvendo uma aplicação usando hibernate. Já fiz a parte para usar os Set de relacionamentos para popular tabelas (Endereços, Telefones, coisas do gênero) e é meio trabalhoso quando tenho q fazer alguma alteraçao.
Nesse caso é melhor continuar usando Set ou mudar pra List, uma vez que não haverão entidades duplicadas?[/quote]

Dentro de TableModels eu geralmente uso lists. Normalmente é uma boa idéia copiar o conteúdo do set externo mesmo:

[code]public UmTableModel<T> extends AbstractTableModel
List<T> elements;

public UmTableModel(Collection<? extends T> elements) {
this.elements = new ArrayList<T>(elements); //Copiamos do set para o list
}
}[/code]

Na classe de negócio é uma boa manter o set, já que ele impõe certas regras, como impedir duplicatas.

Bacana! Valeu pelo toque!