jtable

41
Criando um grid em Java com JTable A Classe JTable é a classe responsável por representar um grid no swing, ao meu ver é umas das classes de GUI mais difícil de se trabalhar pela sua flexibilidade. Esta é uma classe que usa o padrão MVC(Model , View e Controller): Model: é a classe responsável por representar os dados da tabela, sempre que iremos modificar os dados de uma JTable deve ser feito através do objeto model que é implementado pela interface TableModel ( AbstractTableModel e DefaultTableModel). View: É a apresentação da célula na JTable é implementado pela interface CellRenderer, que através de seus métodos define como serão apresentados os valores. Controller: é a parte que controla os dados e a apresentação, ele é representado pela própria JTable. Vejamos agora como criar a mais simples das JTable: 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 serão os nomes das colunas e os usaremos para construir nossa JTable, 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 tipo Vector Na linha 8 criamos o objeto JTable passando como argumento para o construtor dos dados e os nomes das colunas, com este construtor ele cria internamente um objeto DefaultTableModel para armazenar os dados que

Upload: andre-jorge

Post on 23-Nov-2015

72 views

Category:

Documents


1 download

TRANSCRIPT

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