AJXeneize
Criando um grid em Java com JTableA ClasseJTable a classe
responsvel por representar um grid noswing, ao meu ver umas das
classes de GUI mais difcil de se trabalhar pela sua flexibilidade.
Esta uma classe que usa o padro MVC(Model , View e Controller):
Model: a classe responsvel por representar os dados da tabela,
sempre que iremos modificar os dados de uma JTable deve ser feito
atravs do objeto model que implementado pela
interfaceTableModel(AbstractTableModeleDefaultTableModel).
View: a apresentao da clula naJTable implementado pela
interfaceCellRenderer, que atravs de seus mtodos define como sero
apresentados os valores.
Controller: a parte que controla os dados e a apresentao, ele
representado pela prpriaJTable.
Vejamos agora como criar a mais simples dasJTable:
String[] colunas = new String[]{"Nome","Idade","Sexo"};
String[][] dados = new String[][]{
{"Rodrigo","28","Masculino"},
{"Maria","30","Feminino"}
};
JTable tabela = new JTable(dados,colunas);
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(tabela);
this.add(scroll);
Na lina 1 criamos uma array de strings que sero os nomes das
colunas e os usaremos para construir nossaJTable, na linha 3
criamos uma matriz que ser utilizada como dados da tabela, sendo o
primeiro ndice as linhas e o segundo as colunas sendo assim nossa
tabela de exemplo tem 2 linha e 3 colunas. No exemplo utilizamos
uma matriz de String, mas poderia ser uma matriz de Object ou
objeto do tipoVectorNa linha 8 criamos o objetoJTablepassando como
argumento para o construtor dos dados e os nomes das colunas, com
este construtor ele cria internamente um objeto
DefaultTableModelpara armazenar os dados que posteriormente podemos
pegar utilizando o mtodotabela.getModel().
Na linha 9 criamos umJScrollPanepara colocar a tabela dentro
atravs do seu mtodo setViewportView(JTable), ele serve para a
tabela possuir uma barra de rolagem e mostrar os nomes das
colunas.
Na linha 11 adicionamos oJScrollPanena janela.
Tambm poderiamos ter criado a mesma tabela atravs do seguinte
cdigo:
String[] colunas = new String[]{"Nome","Idade","Sexo"};
String[][] dados = new String[][]{
{"Rodrigo","28","Masculino"},
{"Maria","30","Feminino"}
};
JTable tabela = new JTable();
DefaultTableModel model = new DefaultTableModel(dados , colunas
);
tabela.setModel(model);
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(tabela);
this.add(scroll);
Como podemos ver criamos um objetoDefaultTableModel(linha 8),
com os dados da tabela e os nomes das colunas em vez de passar para
para o construtor deJTable, e depois adicionamos o model criado
atravs do mtodosetModel, devemos fazer assim quando quisermos criar
nossos prprios models.
Adicionando uma linha:
DefaultTableModel model = (DefaultTableModel)
tabela.getModel();
String[] linha = new String[]{"Joo", "15" , "Masculino"};
model.addRow(linha);
Como vimos, para manipular os dados de umJTabledevemos utilizar
o objeto model que ela possui, ento primeiro devemos pegar o model
atravs do mtodogetModel(), aps isto basta criar um array de Strings
com os valores correspondentes a cada coluna e adiciona-lo atravs
do mtodoaddRow(), do objeto model.
Removendo uma linha da tabela
DefaultTableModel model = (DefaultTableModel)
tabela.getModel();
model.removeRow(0);
Para remover uma linha devemos primeiro pegar o model
doJTablecomo antes e depois chamar o mtodoremoveRow()que recebe
como parmetro um inteiro que ser o nmero da linha que ele deve
excluir, lembrando que as linha so contadas iniciando em 0.
Na maior parte dos caso queremos remover um linha doJTableque
esta selecionada, para isso devemos pegar o nmero desta linha.
int linha = tabela.getSelectedRow();
if( linha != -1){
tabela.removeRow( linha );
}
Como vemos na linha 1, para descobrir qual linha est selecionada
utilizamos o mtodogetSelectedRow()daJTable, que retorna o numero da
linha selecionada ou-1se no tiver nenhuma linha selecionada.
Bom no adianta nada ter uma tabela se no podemos manipular os
valores dela, veremos abaixo como pegar um valor de uma clula
doJTable
int linha = tabela.getSelectedRow();//pegando linha
selecionada
String nome = tabela.getValueAt(linha , 0) );
String idade = tabela.getValueAt(linha , 1) );
String sexo = tabela.getValueAt(linha , 2) );
O modo mais fcil de pegar um valor de uma clula de umaJTable
atravs do mtodo getValueAt(int , int), que recebe como primeiro
parmetros o nmero da linha e como segundo o nmero da coluna,
lembrando que como as linhas a numerao das colunas comea em 0.
Para colocar um valor especifico em uma clula podemos utilizar o
mtodosetValueAt(Object, int, int):
int linha = tabela.getSelectedRow();//pegando linha
selecionada
tabela.setValueAt("Nome alterado" , linha , 0);
tabela.setValueAt("0" , linha , 1);
tabela.setValueAt("indefinido" , linha , 2);
Ao utilizargetValueAt(int , int)esetValueAt(Objec , int , int
)voc pode querer percorrer todas as linhas ou colunas daJTablee
para isso os mtodosgetRowCount()e getColumnCount()que retornam
respectivamente o nmero de linhas e colunas.
Tambm podemos pegar todos os dados da tabela pegando o objeto
Vector que representa os dados da tabela atravs do
mtodogetDataVector()
Iterator iterator = model.getDataVector().iterator();
while ( iterator.hasNext() ) {
Vector row = (Vector) iterator.next();
System.out.println(row.get(0));
System.out.println(row.get(1));
System.out.println(row.get(2));
}
Como vimos na linha 1 pegamos oVectordo model e utilizamos um
iterator para percorrer as linhas, sendo que cada linha tambm
armazenada como umVector, sendo cada um dos objetos armazenados
nele o valor de uma clula. S lembrando, se voc modificar oVector
retornado pelo mtodogetDateVector()os dados visualizados
naJTablesero modificados.
Esta a maneira mais simples de trabalhar comJTable, para
customizarmos mais ela teremos criar o nosso
prprioTableModeleCellRendererque veremos em prximos posts, eu
espero.
Instanciando um JTable, j inserindo dentro de um JScroll, que
desabilita o usurio poder editar suas clulas:
int linhas = 10;
int colunas = 2;
JTable table = new JTable(linhas, colunas) {
public boolean isCellEditable(int rowIndex, int vColIndex) {
return false;
}
};
JScrollPane scrollPane = new JScrollPane(table);
Bloqueia o usurio de redimensionar as colunas da tabela:
table.getTableHeader().setResizingAllowed(false);
Bloqueia o usurio de trocar a posio das colunas via drap and
drop.
table.getTableHeader().setReorderingAllowed(false);
Alterando o nome das duas primeiras colunas da tabela
dinmicamente:
table.getColumnModel().getColumn(0).setHeaderValue("Coluna
1");
table.getColumnModel().getColumn(1).setHeaderValue("Coluna
2");
Definindo um tamanho fixo para largura das duas primeiras
colunas:
table.getColumnModel().getColumn(0).setPreferredWidth(115);
table.getColumnModel().getColumn(1).setPreferredWidth(661);
Desativando o auto redimensionamento da tabela:
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
Permite apenas seleo simples (somente 1 linha):
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);Tratando
evento de dois clicks do mouse em cima de uma linha da Tabela:
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
JTable target = (JTable)e.getSource();
int linha = target.getSelectedRow(); // linha selecionada
int coluna = target.getSelectedColumn(); // coluna
selecionada
System.out.println("Linha: " + linha);
System.out.println("Coluna: " + coluna);
}
}
});
Espero que essas dicas possam ajudar voc de alguma forma. Todas
elas foram teis para mim em algum momento, portanto achei
importante compartilhar.
Bloqueando a seleo de linhas/colunas baseado em uma determinada
condio.
int linhas = 10;
int colunas = 3;
JTable table = new JTable(linhas, colunas) {
public void changeSelection(int row, int column, boolean toggle,
boolean extend) {
DefaultTableModel m = (DefaultTableModel) getModel();
/* no permite a seleo quando o valor da coluna 3 for igual
fechado */
if (m.getValueAt(row, 2) != null && m.getValueAt(row,
2).toString().toLowerCase().equals("fechado")) {
return;
}
super.changeSelection(row, column, toggle, extend);
}
};
Alterando a cor de fundo/primeiro plano de acordo com uma
determinada condio.
Determina tambm a cor de fundo/primeiro plano da linha
selecionada. Voc esta livre para inserir outras lgicas que achar
necessrio alm desse exemplo bsico que verifica somente o valor de
uma determinada coluna.
int linhas = 5;
int colunas = 3;
JTable table = new JTable(linhas, colunas) {
public Component prepareRenderer(TableCellRenderer renderer,
int rowIndex, int vColIndex) {
DefaultTableModel m = (DefaultTableModel) getModel();
Component c = super.prepareRenderer(renderer, rowIndex,
vColIndex);
// altera a cor de background da linha para vermelho e
foreground para branco
// quando o valor da coluna 3 for igual a fechado
if (m.getValueAt(rowIndex,
2).toString().toLowerCase().equals("fechado")) {
c.setBackground(new Color(192, 0, 0));
c.setForeground(Color.white);
} else {
// mantem a cor padro de foreground
c.setForeground(getForeground());
// determina a cor de background da linha selecionada
if(isCellSelected(rowIndex, vColIndex)) {
c.setBackground(new Color(184, 207, 229));
} else {
// linhas no selecionadas, manter cor de background padro
c.setBackground(getBackground());
}
}
return c;
}
};
Forar a renderizao do JTable
O cdigo abaixo pode ser utilizado para renderizar o JTable
novamente quando for preciso. No caso de mudana de dados que
influencie na lgica usada em algum dos mtodos anteriores.
table.updateUI();
Manipulando o contedo da tabela
// inserindo dados em uma tabela com 4 colunas
DefaultTableModel tableModel = (DefaultTableModel)
minhaTabela.getModel();
tableModel.insertRow(tableModel.getRowCount(), new Object[]{
"Douglas", "Villanacci", "[email protected]",
"11111111"});
tableModel.insertRow(tableModel.getRowCount(), new Object[]{
"Fulano", "da Silva", "[email protected]", "11111111"});
// limpando todo o contedo da tabela
DefaultTableModel tableModel = (DefaultTableModel)
minhaTabela.getModel();
tableModel.getDataVector().removeAllElements();
minhaTabela.updateUI();
// alterando o valor de determinada linha e coluna da tabela:
Linha 1, Coluna 1// linha e coluna comeam com valor 0
TableModel model = (TableModel) minhaTabela.getModel();
model.setValueAt("Josefina", 0, 0);
// obtendo valor de determinado campo na tabela, informando
Linha(2) e Coluna(1)
// linha e coluna comeam com valor 0
TableModel model = (TableModel) minhaTabela.getModel();
String value = (String) model.getValueAt(1, 0);
System.out.println(value);
Tratando evento de mudana de dados na tabelaCaso voc tenha
campos editveis na sua tabela, voc pode em algum momento querer
executar alguma ao quando um valor de um campo da sua tabela sofrer
alteraes.
Para que voc possa controlar as mudanas realizadas na edio da
sua tabela, necessrio monitorar o evento de alterao atravs do
listener TableModelListener.
// monitorando o evento atravs de TableModelListener
minhaTabela.getModel().addTableModelListener(new
TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
int linha = e.getFirstRow();
int coluna = e.getColumn();
TableModel model = (TableModel) e.getSource();
System.out.println("Voc alterou a linha " + linha + ", coluna "
+ coluna);
System.out.println("Valor da clula alterada: " +
model.getValueAt(linha, coluna));
}
});
Usando ComboBox (JcomboBox) nas clulas da sua tabela
possvel associar um JComboBox (caixa de seleo) uma coluna da sua
tabela. uma forma de facilitar a vida do usurio. Ao invs do usurio
digitar um valor para a clula, ele simplesmente escolhe um valor
dentre vrios, atravs de uma caixa de seleo. Recurso bem
interessante e elegante.
No exemplo abaixo, vamos associar um combo box para a quinta
coluna da tabela. (Lembre-se que a numerao das colunas comea por
0). O usurio poder escolher entre Masculino ou Feminino:
// Obtendo referencia para a 5 coluna da tabela
TableColumn column =
minhaTabela.getColumnModel().getColumn(4);
// Criando o ComboBox
JComboBox comboSexo = new JComboBox();
// Definindo os valores para o ComboBox
DefaultComboBoxModel comboModel = new DefaultComboBoxModel(new
String[] { "Masculino", "Feminino" });
comboSexo.setModel(comboModel);
// Associando o ComboBox para a coluna
column.setCellEditor(new DefaultCellEditor(comboSexo));
Selees do usurio
Na sua configurao padro, uma mesa de suporte de uma seleco, que
consiste em uma ou mais linhas. O usurio pode selecionar um
intervalo contguo de linhas ou um conjunto arbitrrio de linhas. A
ltima clula que o usurio indicado recebe uma indicao especial, no
olhar do metal e sentir, a clula est delineado. Esta clula
conhecida como a seleco de chumbo , que por vezes chamado de "clula
com o foco" ou "a clula corrente".
O utilizador utiliza o rato e / ou o teclado para fazer seleces,
tal como descrito na seguinte tabela:
OperaoAo do mouseAo teclado
Selecione uma nica linha.Clique.Seta para cima ou Seta para
baixo.
Estender a seleo contgua.Shift + clique ou arraste sobre
linhas.Seta ou Shift + Seta para baixo Shift-Up.
Adicionar linha para seleo / seleo de linha de
alternncia.Control-ClickMova levar a seleo com Control-Seta para
cima ou Control-Seta para baixo, em seguida, usar a barra de espao
para adicionar seleo ou Control + Barra de Espao para mudar a
seleco de linha.
Este programa de exemplo apresenta a mesa familiar, e permite ao
usurio manipular certas opes JTable. H tambm um painel de texto que
regista eventos de seleco.
Na imagem abaixo, um usurio executar o programa, clicar na
primeira linha, em seguida, controlar clicado na terceira fila.
Observe o contorno ao redor da ltima clula clicada, esta a forma
como o metal olhar e sentir destaques da seleo principal.
Em "Modo de seleco" h um conjunto de botes de rdio. Clique na
caixa "Seleo Single". Agora voc pode selecionar apenas uma linha de
cada vez. Se voc clicar no boto "Single Interval Selection" de
rdio, voc pode selecionar um conjunto de linhas que devem ser
contguos.
Todos os botes de rdio em "Modo Seleco" invocar
JTable.setSelectionMode . Este mtodo recebe um nico argumento, que
deve ser uma das seguintes constantes definidas na
javax.swing.ListSelectionModel : MULTIPLE_INTERVAL_SELECTION ,
SINGLE_INTERVAL_SELECTION e SINGLE_SELECTION .
Voltando a TableSelectionDemo , observe as trs caixas de seleo
de opes em "Opes de seleo". Cada uma opo controla o estado de um
boolean varivel ligada definido pela JTable :
"Seleo Row" controla rowSelectionAllowed que mtodo setter
setRowSelectionAllowed mtodo e getter getRowSelectionAllowed .
Quando essa propriedade bound verdade (ea columnSelectionAllowed
propriedade falso ), o usurio pode selecionar a linha.
"Seleo de coluna" controla columnSelectionAllowed que mtodo
setter setColumnSelectionAllowed mtodo e getter
getColumnSelectionAllowed .Quando essa propriedade bound verdade
(ea rowSelectionAllowed propriedade bound falso ), o usurio pode
selecionar a coluna.
"Seleo de clula" controles cellSelectionEnabled , que tem setter
mtodo setCellSelectionEnabled e mtodo getter
getCellSelectionEnabled .Quando essa propriedade bound verdadeiro ,
o usurio pode selecionar uma nica clula ou bloco retangular de
clulas.
SHAPE \* MERGEFORMAT
NOTA: JTable usa um conceito muito simples de seleo, gerenciada
como uma interseco de linhas e colunas. Ele no foi projetado para
lidar com as selees de clulas totalmente independentes.
SHAPE \* MERGEFORMAT
Se voc desmarcar todas as trs caixas de seleo (definindo todas
as trs propriedades ligadas a falsa ), no h nenhuma seleo, apenas a
seleo principal mostrada.
Voc pode perceber que a opo "celular Selection" desativado no
modo de seleo mltipla intervalo. Isso ocorre porque a seleo celular
no compatvel com este modo na demonstrao. Voc pode especificar a
seleo de clula em modo de seleo mltipla intervalo, mas o resultado
uma tabela que no produz selees teis.
Voc tambm pode perceber que a mudana de qualquer uma das trs
opes de seleo pode afetar os outros. Isso ocorre porque permite
tanto a seleo de linha e coluna seleo exatamente o mesmo que
permite a seleo de clulas. JTable atualiza automaticamente as trs
variveis ligadas como necessrias para mant-los consistentes.
SHAPE \* MERGEFORMAT
NOTA: Ajuste cellSelectionEnabled para um valor tem o efeito
colateral de tambm definir tanto rowSelectionEnabled e
columnSelectionEnableda esse valor. Definir tanto
rowSelectionEnabled e columnSelectionEnabled para um valor tem o
efeito colateral de tambm definircellSelectionEnabled a esse valor.
Setting rowSelectionEnabled e columnSelectionEnabled a diferentes
valores tem o efeito colateral de tambm definir
cellSelectionEnabled para false .
SHAPE \* MERGEFORMAT
Para recuperar a seleo atual, use JTable.getSelectedRows que
retorna uma matriz de ndices de linha e JTable.getSelectedColumns
que retorna um array de ndices de coluna. Para obter as coordenadas
da seleo principal, referem-se aos modelos de seleo para a prpria
mesa e para o modelo de coluna da tabela. Os seguintes formatos de
cdigo de uma string contendo a linha e coluna da seleo
principal:
String.format ("Seleo de execuo:.% D,% d",
table.getSelectionModel (). getLeadSelectionIndex () ..
table.getColumnModel () getSelectionModel () getLeadSelectionIndex
());
Selees do usurio gerar uma srie de eventos. Para obter informaes
sobre estes, consulte Como escrever um Listener Seleo Lista no
Writing Evento Ouvinteslio.
SHAPE \* MERGEFORMAT
NOTA: a seleo de dados, na verdade, descreve as clulas
selecionadas no "vista" (dados da tabela que aparece depois de
qualquer classificao ou filtragem), e no no modelo de tabela. Esta
distino no importa a menos que os dados vistos foi adaptada por
classificao, filtragem ou manipulao usurio de colunas. Nesse caso,
voc deve converter as coordenadas de seleo usando os mtodos de
converso descritos na Classificao e filtragem .
SHAPE \* MERGEFORMAT
Criando um Modelo de Tabela
Cada objeto de tabela usa um objeto modelo de tabela para
gerenciar os dados da tabela de reais. Um objeto de modelo de
tabela deve implementar o TableModelinterface. Se o programador no
fornecer um objeto de modelo de mesa, JTable automaticamente cria
uma instncia de DefaultTableModel . Esta relao ilustrada
abaixo.
O JTable construtor usado por SimpleTableDemo cria seu modelo de
mesa com um cdigo como este:
new AbstractTableModel () { getColumnName public String (int
col) { voltar columnNames [col] toString ().; } public int
GetRowCount () {rowData.length return;} public int getColumnCount
() {columnNames.length return;} public Object getValueAt (int row,
int col) { voltar RowData [row] [col]; } public boolean
isCellEditable (int row, int col) {Return true;} setValueAt public
void (Object value, int row, int col) { RowData [row] [col] =
valor; fireTableCellUpdated (row, col); }}
Como o cdigo anterior mostra, a implementao de um modelo de
tabela pode ser simples. Geralmente, voc implementar seu modelo de
tabela em uma subclasse deAbstractTableModel classe.
Seu modelo pode manter seus dados em uma matriz, vetor, ou mapa
de hash, ou pode obter os dados de uma fonte externa, como um banco
de dados. Pode at gerar os dados em tempo de execuo.
Esta tabela diferente do SimpleTableDemo tabela das seguintes
maneiras:
TableDemo "modelo de tabela personalizada s, embora seja
simples, pode facilmente determinar o tipo dos dados, ajudando a
JTable exibir os dados no melhor formato. SimpleTableDemo criado
automaticamente modelo de tabela, por outro lado, no sabe que o #
Anos de coluna contm nmeros (que geralmente devem ser alinhados
direita e tem um formato particular). Ele tambm no sabe que a
Vegetarian coluna contm valores booleanos, que podem ser
representados por caixas de seleo.
O modelo de tabela personalizada implementado em TableDemo no
permite que voc edite as colunas de nome, mas, no entanto, permitem
que voc edite as outras colunas. Em SimpleTableDemo , todas as
clulas so editveis.
Mais abaixo feita a partir do cdigo TableDemo.java que diferente
do SimpleTableDemo.java . Negrito indica o cdigo que faz com que
este modelo de mesa diferente do modelo de tabela definida
automaticamente para SimpleTableDemo .
pblico TableDemo () { ... Mesa JTable = new JTable (new
MyTableModel ()); ...}
MyTableModel classe estende AbstractTableModel { private String
[] columnNames = ... / / mesmo que antes ...
private Object [] [] data = ... / / mesmo que antes ... pblico
getColumnCount int () { voltar columnNames.length; }
pblico GetRowCount int () { voltar data.length; }
getColumnName public String (int col) { voltar columnNames
[col]; }
public Object getValueAt (int row, int col) { retornar dados
[row] [col]; }
getColumnClass Classe pblica (int c) { voltar getValueAt (0, c)
getClass ().; } / * * No precisa implementar este mtodo, a menos de
sua mesa * Editvel. * / public boolean isCellEditable (int row, int
col) { / / Note que o endereo de dados / clula constante, / / No
importa onde a clula aparece na tela.
if (col