Tutorial sobre JTable - Parte 2: Implementando Seu Modelo
em 22/06/2004
, por Bruno Rios Lima
Agora que temos onde guardar os dados que queremos exibir, devemos implementar os métodos que fornecem a JTable os dados suficientes para ela saber montar a parte visual: o numero de colunas, numero de linhas e os valores para preencher as células:
Agora, devemos criar o construtor da classe que irá receber os dados e as colunas que desejamos.
A partir disto, já temos o nosso modelo pronto para exibir os dados contido nele. Agora vamos criar uma apresentação simples utilizando este nosso modelo. Vamos criar algo parecido com a do exemplo da primeira parte deste tutorial, e usaremos o mesmo nome: MyTableViewer. Abaixo segue como deve ficar o método que cria a JTable :
Observe que o método acima alimenta as variáveis: dados agora é um ArrayList, e incluímos nele diversos arrays de String , pois é o esperado dentro da linha ( veja a implementação do método getValueAt ). Se rodarmos o código agora, ele irá apresentar a Jtable com nossos dados, e não irá permitir alterar, diferentemente do modelo DefaultTableModel. Isso porque não implementamos o método isCellEditable, e ele acabou herdando do AbstractTableModel, que retorna false para todas as células. No default, este método retorna true.
Você pode deixar separado o controle de edição de suas células, permitindo em tempo de execução quando determinada célula irá permitir alteração. Neste exemplo vamos permitir que seja informado, na criação do modelo, quais colunas vamos permitir edição e quais não. Para isso, vamos ter uma variável que é um array de boolean que guardará o valor de cada coluna.
E vamos alterar o construtor para receber esse novo parâmetro:
O método para setar o valor, nada mais faz do que obter o objeto na linha e coluna e altera-lo. Porém, devemos lembrar que quando é feito uma alteração do conteúdo do modelo, devemos informar a JTable. Fazemos isso atraves do método fireTableCellUpdated.
Para visualizarmos as alterações que permitem alterar o valor da célula na JTable, devemos fazer as seguintes alterações na apresentação ( MyTableViewer ) no método de criação da JTable:
Exclusao de linhas existentes Assim como a inclusão de linhas, a exclusão delas é feita diretamente pelo modelo dos dados da jtable. E funciona assim como na inclusão. Devemos remover a linha passada pelo parâmetro. Usando um ArrayList, podemos excluir diretamente pelo indice dele. Ou, podemos esperar um campo contido na linha, fazemos um looping nos dados para verificar o conteúdo. Abaixo, veremos esses dois exemplos de exclusão. Um problema que devemos tomar cuidado é que, se informado uma linha que não existe no modelo, então o método remove do ArrayList irá disparar um IndexOutOfBound, ou seja, não existe indice informado dentro do array. Você pode tratar isso verificando se o parâmetro informado irá passar dos limites do array ( se ele é negativo e se é maior ou igual ao tamanho total do array ).
Para evitar que a JTable crie as colunas nela automaticamente, devemos setar a propriedade AutoCreateColumnsFromModel para false. Neste caso, devemos criar as colunas na mão. Conclusão Tenha em mente uma coisa: dentro do modelo, não importa como você armazene seus dados. Não interessa para a JTable se você usou a classe mais avançada, se buscou na hora direto do seu banco, ou se está tudo em um array. O importante é fornecer o valor atraves dos métodos, e informar das alterações ocorridas no seu modelo. Assim, você poderá implementar de diversas formas o seu modelo. Futuramente iremos trabalhar usando os Renderers e Editors. Com eles, poderemos utilizar qualquer classe para exibir ou armazenar e logo veremos a vantagem de se implementar o seu próprio modelo. No proximo tutorial, iremos ver como criar as colunas direto na JTable, sem deixar que elas sejam criadas automaticamente pelo modelo. Tambem iremos ver como criar nossos próprios renderers e editors para usar na tabela. Aguardem! Abraços e até o proximo tutorial!
Tutorial sobre JTable - Parte 2: Implementando Seu Modelo
Bem vindo à parte 2 do tutorial sobre JTable. O primeiro artigo voce encontra clicando aqui.Nesta parte iremos criar o nosso próprio modelo de tabela e aprenderemos a trabalhar com ele.
Implementado o TableModel
No nosso primeiro tutorial foi dado uma pequena palinha de como uma implementação de um TableModel deve ser feita, utilizando a classe abstrata AbtractTableModel.
Se não se lembra, a classe abstrata AbstractTableModel implementa diversas funcionalidades da TableModel: incluindo os eventos que disparam para a JTable alterações ocorridas nos dados do modelo. Estes métodos estão disponíveis para uso nas subclasses, pois são métodos internos do modelo. Agora, com relação aos métodos que tratam os dados propriamente ditos, não é implementado nenhum método: isso significa que você deverá implementar do melhor jeito ( pelo menos que você ache ) de armazenar os dados que serão exibidos pela JTable e que o modelo irá fornecer a ela.
O modelo de dados funciona como um repositório dos dados, portanto ele deve armazenar-los em algum lugar: nada melhor do que um array para armazenas o conteúdo das linhas. Agora, imagine que, em cada linha, podemos ter 2 colunas. Como armazenar 2 colunas dentro de um array? Podemos usar um array de String de tamanho 2, por exemplo. Ou até mesmo outro array do tipo java.util.List. Por ser um conteúdo dinâmico ( que pode ser alterado em tempo de execução: exemplo remover ou incluir novas linhas ) , nunca podemos saber o tamanho exato maximo que esse array dos dados terá. Por isso, o melhor jeito é ter uma Collection para armazena-lo. Neste exemplo vamos usar a classe java.util.ArrayList para armazenar os dados da linha e um array de String para colunas.
Primeiro, vamos criar a classe e suas variáveis internas que irão guardar o dados do nosso modelo:
Agora que temos onde guardar os dados que queremos exibir, devemos implementar os métodos que fornecem a JTable os dados suficientes para ela saber montar a parte visual: o numero de colunas, numero de linhas e os valores para preencher as células:
Agora, devemos criar o construtor da classe que irá receber os dados e as colunas que desejamos.
Observe que o método acima alimenta as variáveis: dados agora é um ArrayList, e incluímos nele diversos arrays de String , pois é o esperado dentro da linha ( veja a implementação do método getValueAt ). Se rodarmos o código agora, ele irá apresentar a Jtable com nossos dados, e não irá permitir alterar, diferentemente do modelo DefaultTableModel. Isso porque não implementamos o método isCellEditable, e ele acabou herdando do AbstractTableModel, que retorna false para todas as células. No default, este método retorna true.
Alterando o Conteúdo Do Modelo:
Para permitir a edição da célula, e, principalmente, que seu valor venha parar aqui no modelo ( se você implementar somente o método isCellEditable sem o setValueAt, simplesmente ele permite a edição, mas não "fixa" seu valor na célula, pois ele não vem para o seu modelo não refletindo de volta em sua JTable ) devemos implementar os seguintes métodos:
Você pode deixar separado o controle de edição de suas células, permitindo em tempo de execução quando determinada célula irá permitir alteração. Neste exemplo vamos permitir que seja informado, na criação do modelo, quais colunas vamos permitir edição e quais não. Para isso, vamos ter uma variável que é um array de boolean que guardará o valor de cada coluna.
E vamos alterar o construtor para receber esse novo parâmetro:
O método para setar o valor, nada mais faz do que obter o objeto na linha e coluna e altera-lo. Porém, devemos lembrar que quando é feito uma alteração do conteúdo do modelo, devemos informar a JTable. Fazemos isso atraves do método fireTableCellUpdated.
Para visualizarmos as alterações que permitem alterar o valor da célula na JTable, devemos fazer as seguintes alterações na apresentação ( MyTableViewer ) no método de criação da JTable:
Inclusao de novas linhas
Como a jtable não faz inclusão de linhas no modelo diretamente, este método não é uma implementação, ou seja, não é preciso ter uma assinatura especifica.
Para incluir novas linhas, devemos adicionar um novo objeto no array de linhas. Este objeto deve ser do mesmo tipo em todas as linhas, ou seja, se for utilizar um array de String[2], sempre incluir arrays de String[2]. Pois no método getValueAt você tem que saber o que pegar nas linhas.
Abaixo segue um exemplo de um método, bem simples, para incluir uma nova linha no modelo.
Exclusao de linhas existentes Assim como a inclusão de linhas, a exclusão delas é feita diretamente pelo modelo dos dados da jtable. E funciona assim como na inclusão. Devemos remover a linha passada pelo parâmetro. Usando um ArrayList, podemos excluir diretamente pelo indice dele. Ou, podemos esperar um campo contido na linha, fazemos um looping nos dados para verificar o conteúdo. Abaixo, veremos esses dois exemplos de exclusão. Um problema que devemos tomar cuidado é que, se informado uma linha que não existe no modelo, então o método remove do ArrayList irá disparar um IndexOutOfBound, ou seja, não existe indice informado dentro do array. Você pode tratar isso verificando se o parâmetro informado irá passar dos limites do array ( se ele é negativo e se é maior ou igual ao tamanho total do array ).
Retornando o Titulo da Coluna
Este método retorna uma String com o titulo da coluna. A JTable irá chamar este método para obter o titulo da coluna e colocar no Header, quando suas colunas forem criadas automaticamente a partir do seu modelo.
Para evitar que a JTable crie as colunas nela automaticamente, devemos setar a propriedade AutoCreateColumnsFromModel para false. Neste caso, devemos criar as colunas na mão. Conclusão Tenha em mente uma coisa: dentro do modelo, não importa como você armazene seus dados. Não interessa para a JTable se você usou a classe mais avançada, se buscou na hora direto do seu banco, ou se está tudo em um array. O importante é fornecer o valor atraves dos métodos, e informar das alterações ocorridas no seu modelo. Assim, você poderá implementar de diversas formas o seu modelo. Futuramente iremos trabalhar usando os Renderers e Editors. Com eles, poderemos utilizar qualquer classe para exibir ou armazenar e logo veremos a vantagem de se implementar o seu próprio modelo. No proximo tutorial, iremos ver como criar as colunas direto na JTable, sem deixar que elas sejam criadas automaticamente pelo modelo. Tambem iremos ver como criar nossos próprios renderers e editors para usar na tabela. Aguardem! Abraços e até o proximo tutorial!