Prof: Sérgio Souza Costa
JTableView e MVC
Sobre mim
Sérgio Souza Costa
Professor - UFMA
Doutor em Computação Aplicada (INPE)
prof.sergio.costa@gmail.com
https://sites.google.com/site/profsergiocosta/home
https://twitter.com/profsergiocosta
http://gplus.to/sergiosouzacosta
http://www.slideshare.net/skosta/presentations?order=popular
Dando sequência, o desafio de hoje é
conseguir carregar os dados de uma tabela e
mostrar na interface gráfica.
public List<Contato> recupera () {
String sql = "select * from contato";
List<Contato> contatos = new ArrayList<Contato>();
try {
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Contato contato = new Contato();
contato.setNome(rs.getString("nome"));
contato.setTelefone(rs.getString("telefone"));
contato.setEmail(rs.getString("email"));
contatos.add(contato);
}
stmt.close();
} catch (SQLException u) {
throw new RuntimeException(u);
}
return contatos;
}
Antes de começarmos, vamos precisar ter o
método “recupera” na classe ContatoDAO
que retorna a lista de contatos do banco de
dados.
Eu vi que o Swing possui um controle
gráfico, chamado JTable. Mas como
faço para utilizá-lo ?
O Jtable apresenta uma grade
multidimensional de objetos.
Por exemplo, é possível construir
tabelas simples através de um array
bidimensional de objetos.
JTable(Object[][] dados, Object[] nomeColunas)
//dados : as células da tabela
//nomesColunas : os títulos da coluna
Object[][] data = {
{"João", "Carlos", “Natação", new Integer(5)},
{"Francisco", "Silva", "Remo", new Integer(3)},
{"Fernando", "Cardoso","Montanismo", new Integer(2)},
{"Luís Inácio", "Silva","Futebol", new Integer(20)},
{"Angela", "Maria","Rapel", new Integer(4)}
};
String[] colunas = {"Nome","Sobrenome","Esporte",
"Prática (ano)","Vegetariano"};
final JTable table = new JTable(data , colunas );
Exemplo usando array
Contudo, as tabelas podem ser
dinâmicas e acessando diferentes
fontes de dados (datasources).
Precisando ser mais versátil.
O Swing consegue isso
implementando o Jtable como um
componente MVC.
Como assim ?
O modelo (dados) é separado da
visualização.
Model
(TableModel)
View
(JTable)
JTable(TableModel dm)
As principais classes são:
● JTable -- view
● TableModel -- Interface
(getValueAt(), setValueAt, getRowCount(),
getColumnCount(), ...
● TableModelListener -- Interface
( tableChanged())
● AbstractTableModel -- implementa alguns métodos
não diretamente relacionadas ao armazenamento
addTableModelListener(),
removeTableModelListener(),
● DefaultTableModel -- classe concreta usando array
Então, o DefaultTableModel pode ser
usado quando seus dados são
estáticos.
Lembra do código do slide 9 ? O código
abaixo é equivalente. Nele mostro o
uso explícito do DefaultTableModel
Object[][] data = {
{"João", "Carlos", "Natação", new Integer(5)},
{"Francisco", "Silva", "Remo", new Integer(3)},
};
String[] colunas = {"Nome","Sobrenome","Esporte",
"Prática (ano)","Vegetariano"};
DefaultTableModel tm = new
DefaultTableModel(data, colunas);
JTable t = new JTable(tm );
Entendi, basta carregar os dados do
banco, convertê-los para array, e
construir um DefaultTableModel.
Calma, no caso de banco de dados
esta não é a melhor solução.
Ao invés disso construímos nossa
própria classe TableModel. Vamos ver
melhor a camada modelo.
Camada Modelo
A classe abstrata AbstractTableModel que implementa a interface
TableModel fornece a maioria dos métodos exigidos. É necessário
fornecer principalmente implementações para três métodos abaixo:
public int getRowCount( )
public int getColumCount( )
public Object getValueAt(int linha, int coluna)
– é responsável por fornecer os dados para a tabela, a qual
requisitará os dados através do método getValueAt, informando a
linha e a coluna
Camada Modelo
• Alguns métodos definidos em AbstractTableModel oferecem um maior grau de
controle:
– public String getColumnName(int col)
• Se não for fornecido nomes de colunas, o método getColumnName do
modelo AbstractTableModel atribuíra os nome A, B, C, e assim por
diante
• Para mudar o nome das colunas é necessário substituir o método
getColumnName
– public boolean isCellEditable(int rowIndex, int columnIndex)
• Não é obrigatório redefinir este método
• O valor retornado por padrão é false
Camada de Modelo
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
A redefinição deste método fornece mais informações sobre o tipo da
coluna, pois retorna a classe que representa o objeto
Exibidores padrão:
21
Tipo Exibe como
Imagem imagem
Boolean checkBox (caixa de seleção)
Object String
Visualização e Controle
Camada de Visualização (View): É a parte que cuida da apresentação
– É implementado pela interface CellRenderer. É como a
apresentação é dada célula a célula na tabela
Controlador: é a parte que controla a apresentação dos dados na view
– É o JTable
22
• DefaultTableModel fornece todo o controle dos dados do JTable
– getValueAt(): recupera o valor de uma determinada linha e coluna
– setValueAt(): seta o valor em uma determinada linha e coluna
– addRow(): adiciona uma nova linha no JTable. Recebe um array
simples
– addColumn(): adiciona uma nova coluna no modelo
23
DefaultTableModel
24
String[][] dados = new String [][]{
{"SP","Sao Paulo"},
{"RJ","Rio de Janeiro"},
{"RN","Rio Grande do Norte"},
{"PR","Parana"}
};
String[] colunas = new String []{"Estado","Cidade"};
// Adiciona os dados em um modelo
DefaultTableModel modelo = new
DefaultTableModel(dados, colunas);
// e passamos o modelo para criar a jtable
JTable jtable = new JTable( modelo );
DefaultTableModel
Vamos a prática
public class ContatoTableModel extends
AbstractTableModel {
private List<Contato> contatos;
private List<String> colunas;
private ContatoDAO dao;
public ContatoTableModel (ContatoDAO dao){
this.dao = dao;
this.contatos = dao.recupera();
colunas = Arrays.asList("Nome", "Email");
}
public int getRowCount() { return contatos.size(); }
public int getColumnCount() {return colunas.size(); }
public String getColumnName(int i){
return colunas.get(i);
}
public Object getValueAt(int r, int c) {
Contato contato = contatos.get(r);
switch (c) {
case 0 : return contato.getNome();
case 1 : return contato.getEmail();
}
return null;
}
}
Crie uma classe
ContatoTableModel:
public class FrameTable extends JFrame {
public FrameTable (){
super(”Contatos");
ContatoDAO dao = new ContatoDAO();
ContatoTableModel tm =
new ContatoTableModel (dao);
JTable t = new JTable (tm);
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(t);
add(scroll);
setSize(200, 180);
}
public static void main(String[] args) {
FrameTable f = new FrameTable();
f.setVisible(true);
}
}
Para vermos o resultado.
Basta criar um frame com
apenas um Jtable.
public class FrameTable extends JFrame {
public FrameTable (){
super(”Contatos");
ContatoDAO dao = new ContatoDAO();
ContatoTableModel tm =
new ContatoTableModel (dao);
JTable t = new JTable (tm);
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(t);
add(scroll);
setSize(200, 180);
}
public static void main(String[] args) {
FrameTable f = new FrameTable();
f.setVisible(true);
}
}
Jtable não implementa as
barras de rolagem. Para isso
adicionamos o Jtable ao
JScrollPane.
Este é o resultado do código anterior
Legal. Mas eu quero tornar o Jtable
editável. Então, eu codifiquei o
seguinte método para a classe
“ContatoTableModel”
@Override
public boolean isCellEditable(int r, int c) {
return true;
}
Com este método Jtable passou me deixar
alterar o valor, porém quando eu clico
“enter” os valores não são alterados.
public void setValueAt(Object aValue, int r, int c) {
// Pega o contato referente a linha especificada.
Contato contato = contatos.get(r);
switch (c) {
case 0:
contato.setNome((String) aValue);
break;
case 1:
contato.setEmail((String) aValue);
break;
default:
throw new IndexOutOfBoundsException(
"columnIndex out of bounds");
}
fireTableCellUpdated(r, c); // Notifica a atualização da célula
}
Faltou
implementar o
método
setValueAt.
Sim. Porém, quando reiniciei minha
aplicação, percebi que o Jtable voltou a
mostrar os valores antigos. O banco de
dados não foi atualizado ☹
Observe que o código não faz
nenhuma alteração no banco de
dados.
Qual operação SQL precisamos
executar ?
A operação “Update ….” atualiza uma
determinada linha de uma tabela.
Aonde está operação deve ser
codificada ?
public void atualiza (Contato c) {
String sql = "update contato set nome=?,
email=? where id = ?";
try {
PreparedStatement stmt =
conn.prepareStatement(sql);
stmt.setString(1, c.getNome());
stmt.setString(2, c.getEmail());
stmt.setLong(3, c.getId());
stmt.execute();
stmt.close();
} catch (SQLException u) {
throw new RuntimeException(u);
}
}
Inseri o método atualiza
na classe ContatoDAO.
Mas como vou chamar
esta operação ?
public class ContatoTableModel
extends AbstractTableModel
implements TableModelListener {
private List<Contato> contatos;
private List<String> colunas;
private ContatoDAO dao;
public ContatoTableModel(ContatoDAO dao){
this.dao = dao;
this.contatos = dao.recupera();
colunas = Arrays.asList("Nome", "Email");
this.addTableModelListener(this);
}
….
}
Precisamos tratar o evento
“TableChange”. Para isso fazemos a
seguinte modificação a classe
ContatoTableModel
public void tableChanged(TableModelEvent event) {
int i = event.getFirstRow();
Contato contato = contatos.get(i);
System.out.println(i);
dao.atualiza(contato);
}
Então codificamos o método
tableChanged da classe
ContatoTableModel
YES. Agora sim
Se eu quisesse incluir um
combo box? É possível ?
Sim. Veja o seguinte exemplo.
Adicione a coluna “grupo” a tabela
contato.
alter table contato add grupo
varchar(50);
Modifique as classes Contato,
ContatoDAO e ContatoTableModel para
incluir mais uma coluna.
public FrameTable (){
super("Teste");
final ContatoDAO dao = new ContatoDAO();
ContatoTableModel tm = new ContatoTableModel (dao);
JTable t = new JTable (tm);
JComboBox comboBox = new JComboBox();
comboBox.addItem("Familia");
comboBox.addItem("Amigo");
comboBox.addItem("Conhecido");
t.getColumnModel().getColumn(2).setCellEditor(new
DefaultCellEditor(comboBox));
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(t);
add(scroll);
setSize(200, 180);
}
Crie a combo box e
adicione-a na coluna.
Legal. Mas se a tabela
tivesse outros tipos de
dados, por exemplo,
boolean.
alter table contato add
ativo boolean;
Adicione a coluna ativo a tabela contato
e modifique as classes Contato,
ContatoDAO ....
Mas a coluna ativo
mostra o valor false. Esse
não é um valor esperado
pelo usuário.
A renderização padrão da tabela é string, se
quisermos usar outra precisamos informar o
tipo de dado ao Jtable com o método
getColumnClass.
@Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
O método getColumnClass faz a JTable associar
automaticamente um TableCellRenderer
específico para campos booleanos.
Por exemplo, booleano é renderizado como um
checkbox.
Se eu desejar adicionar
ou remover uma linha ?
Queria usar um banco de dados
mais simples, tipo o Access, ou
seja, que não precise de um
servidor.
De fato, nem sempre precisamos de um
banco de dados robusto em pequenas
aplicações para desktop.
Mesmo em aplicações mais complexas, é comum usar
um banco de dados mais simples no inicio do
desenvolvimento. Depois, com o JDBC, podemos
facilmente mudar para um servidor de banco de dados,
como o Oracle ou mesmo o MySQL.
Se eu desejar adicionar
ou remover uma linha ?
Basta adicionar um novo contato a lista de
contatos da ContatoTableModel e depois
notificar esta mudança ao Jtable através do
método: fireTableDataChanged.
Porém, para salvar no banco de dados,
precisamos adicioná-lo também ao banco.
Então, fazemos assim, criamos um contato apenas
com ID, e adicionamos a tabela. Então o usuário
poderá atualiza-lo com as informações. Para isso
criamos o seguinte método na classe
ContatoTableModel.
public void addContato(){
Contato c = new Contato ()
contatos.add(c);
dao.adiciona(c);
fireTableDataChanged();
}
No construtor da classe FrameTable
adicione os botões adicionar e excluir:
JPanel pan = new JPanel ();
JButton btNovo = new JButton ("Novo");
JButton btExcluir = new JButton ("Excluir");
pan.add(btNovo, BorderLayout.EAST);
pan.add(btExcluir, BorderLayout.EAST);
add(pan, BorderLayout.SOUTH);
Depois, basta adicionar o evento action com
a seguinte codificação
btNovo.addActionListener( new ActionListener () {
@Override
public void actionPerformed (ActionEvent ev){
tm.addContato();
}
});
Desafio: Codifiquem o botão excluir.
Atividade

JTableView - Swing

  • 1.
    Prof: Sérgio SouzaCosta JTableView e MVC
  • 2.
    Sobre mim Sérgio SouzaCosta Professor - UFMA Doutor em Computação Aplicada (INPE) prof.sergio.costa@gmail.com https://sites.google.com/site/profsergiocosta/home https://twitter.com/profsergiocosta http://gplus.to/sergiosouzacosta http://www.slideshare.net/skosta/presentations?order=popular
  • 3.
    Dando sequência, odesafio de hoje é conseguir carregar os dados de uma tabela e mostrar na interface gráfica.
  • 4.
    public List<Contato> recupera() { String sql = "select * from contato"; List<Contato> contatos = new ArrayList<Contato>(); try { PreparedStatement stmt = connection.prepareStatement(sql); ResultSet rs = stmt.executeQuery(); while (rs.next()) { Contato contato = new Contato(); contato.setNome(rs.getString("nome")); contato.setTelefone(rs.getString("telefone")); contato.setEmail(rs.getString("email")); contatos.add(contato); } stmt.close(); } catch (SQLException u) { throw new RuntimeException(u); } return contatos; } Antes de começarmos, vamos precisar ter o método “recupera” na classe ContatoDAO que retorna a lista de contatos do banco de dados.
  • 5.
    Eu vi queo Swing possui um controle gráfico, chamado JTable. Mas como faço para utilizá-lo ?
  • 6.
    O Jtable apresentauma grade multidimensional de objetos.
  • 7.
    Por exemplo, épossível construir tabelas simples através de um array bidimensional de objetos. JTable(Object[][] dados, Object[] nomeColunas) //dados : as células da tabela //nomesColunas : os títulos da coluna
  • 8.
    Object[][] data ={ {"João", "Carlos", “Natação", new Integer(5)}, {"Francisco", "Silva", "Remo", new Integer(3)}, {"Fernando", "Cardoso","Montanismo", new Integer(2)}, {"Luís Inácio", "Silva","Futebol", new Integer(20)}, {"Angela", "Maria","Rapel", new Integer(4)} }; String[] colunas = {"Nome","Sobrenome","Esporte", "Prática (ano)","Vegetariano"}; final JTable table = new JTable(data , colunas ); Exemplo usando array
  • 9.
    Contudo, as tabelaspodem ser dinâmicas e acessando diferentes fontes de dados (datasources). Precisando ser mais versátil.
  • 10.
    O Swing consegueisso implementando o Jtable como um componente MVC.
  • 11.
  • 12.
    O modelo (dados)é separado da visualização. Model (TableModel) View (JTable) JTable(TableModel dm)
  • 13.
    As principais classessão: ● JTable -- view ● TableModel -- Interface (getValueAt(), setValueAt, getRowCount(), getColumnCount(), ... ● TableModelListener -- Interface ( tableChanged()) ● AbstractTableModel -- implementa alguns métodos não diretamente relacionadas ao armazenamento addTableModelListener(), removeTableModelListener(), ● DefaultTableModel -- classe concreta usando array
  • 14.
    Então, o DefaultTableModelpode ser usado quando seus dados são estáticos.
  • 15.
    Lembra do códigodo slide 9 ? O código abaixo é equivalente. Nele mostro o uso explícito do DefaultTableModel Object[][] data = { {"João", "Carlos", "Natação", new Integer(5)}, {"Francisco", "Silva", "Remo", new Integer(3)}, }; String[] colunas = {"Nome","Sobrenome","Esporte", "Prática (ano)","Vegetariano"}; DefaultTableModel tm = new DefaultTableModel(data, colunas); JTable t = new JTable(tm );
  • 16.
    Entendi, basta carregaros dados do banco, convertê-los para array, e construir um DefaultTableModel.
  • 17.
    Calma, no casode banco de dados esta não é a melhor solução.
  • 18.
    Ao invés dissoconstruímos nossa própria classe TableModel. Vamos ver melhor a camada modelo.
  • 19.
    Camada Modelo A classeabstrata AbstractTableModel que implementa a interface TableModel fornece a maioria dos métodos exigidos. É necessário fornecer principalmente implementações para três métodos abaixo: public int getRowCount( ) public int getColumCount( ) public Object getValueAt(int linha, int coluna) – é responsável por fornecer os dados para a tabela, a qual requisitará os dados através do método getValueAt, informando a linha e a coluna
  • 20.
    Camada Modelo • Algunsmétodos definidos em AbstractTableModel oferecem um maior grau de controle: – public String getColumnName(int col) • Se não for fornecido nomes de colunas, o método getColumnName do modelo AbstractTableModel atribuíra os nome A, B, C, e assim por diante • Para mudar o nome das colunas é necessário substituir o método getColumnName – public boolean isCellEditable(int rowIndex, int columnIndex) • Não é obrigatório redefinir este método • O valor retornado por padrão é false
  • 21.
    Camada de Modelo publicClass getColumnClass(int c) { return getValueAt(0, c).getClass(); } A redefinição deste método fornece mais informações sobre o tipo da coluna, pois retorna a classe que representa o objeto Exibidores padrão: 21 Tipo Exibe como Imagem imagem Boolean checkBox (caixa de seleção) Object String
  • 22.
    Visualização e Controle Camadade Visualização (View): É a parte que cuida da apresentação – É implementado pela interface CellRenderer. É como a apresentação é dada célula a célula na tabela Controlador: é a parte que controla a apresentação dos dados na view – É o JTable 22
  • 23.
    • DefaultTableModel fornecetodo o controle dos dados do JTable – getValueAt(): recupera o valor de uma determinada linha e coluna – setValueAt(): seta o valor em uma determinada linha e coluna – addRow(): adiciona uma nova linha no JTable. Recebe um array simples – addColumn(): adiciona uma nova coluna no modelo 23 DefaultTableModel
  • 24.
    24 String[][] dados =new String [][]{ {"SP","Sao Paulo"}, {"RJ","Rio de Janeiro"}, {"RN","Rio Grande do Norte"}, {"PR","Parana"} }; String[] colunas = new String []{"Estado","Cidade"}; // Adiciona os dados em um modelo DefaultTableModel modelo = new DefaultTableModel(dados, colunas); // e passamos o modelo para criar a jtable JTable jtable = new JTable( modelo ); DefaultTableModel
  • 25.
  • 26.
    public class ContatoTableModelextends AbstractTableModel { private List<Contato> contatos; private List<String> colunas; private ContatoDAO dao; public ContatoTableModel (ContatoDAO dao){ this.dao = dao; this.contatos = dao.recupera(); colunas = Arrays.asList("Nome", "Email"); } public int getRowCount() { return contatos.size(); } public int getColumnCount() {return colunas.size(); } public String getColumnName(int i){ return colunas.get(i); } public Object getValueAt(int r, int c) { Contato contato = contatos.get(r); switch (c) { case 0 : return contato.getNome(); case 1 : return contato.getEmail(); } return null; } } Crie uma classe ContatoTableModel:
  • 27.
    public class FrameTableextends JFrame { public FrameTable (){ super(”Contatos"); ContatoDAO dao = new ContatoDAO(); ContatoTableModel tm = new ContatoTableModel (dao); JTable t = new JTable (tm); JScrollPane scroll = new JScrollPane(); scroll.setViewportView(t); add(scroll); setSize(200, 180); } public static void main(String[] args) { FrameTable f = new FrameTable(); f.setVisible(true); } } Para vermos o resultado. Basta criar um frame com apenas um Jtable.
  • 28.
    public class FrameTableextends JFrame { public FrameTable (){ super(”Contatos"); ContatoDAO dao = new ContatoDAO(); ContatoTableModel tm = new ContatoTableModel (dao); JTable t = new JTable (tm); JScrollPane scroll = new JScrollPane(); scroll.setViewportView(t); add(scroll); setSize(200, 180); } public static void main(String[] args) { FrameTable f = new FrameTable(); f.setVisible(true); } } Jtable não implementa as barras de rolagem. Para isso adicionamos o Jtable ao JScrollPane.
  • 29.
    Este é oresultado do código anterior
  • 30.
    Legal. Mas euquero tornar o Jtable editável. Então, eu codifiquei o seguinte método para a classe “ContatoTableModel” @Override public boolean isCellEditable(int r, int c) { return true; }
  • 31.
    Com este métodoJtable passou me deixar alterar o valor, porém quando eu clico “enter” os valores não são alterados.
  • 32.
    public void setValueAt(ObjectaValue, int r, int c) { // Pega o contato referente a linha especificada. Contato contato = contatos.get(r); switch (c) { case 0: contato.setNome((String) aValue); break; case 1: contato.setEmail((String) aValue); break; default: throw new IndexOutOfBoundsException( "columnIndex out of bounds"); } fireTableCellUpdated(r, c); // Notifica a atualização da célula } Faltou implementar o método setValueAt.
  • 33.
    Sim. Porém, quandoreiniciei minha aplicação, percebi que o Jtable voltou a mostrar os valores antigos. O banco de dados não foi atualizado ☹
  • 34.
    Observe que ocódigo não faz nenhuma alteração no banco de dados.
  • 35.
    Qual operação SQLprecisamos executar ?
  • 36.
    A operação “Update….” atualiza uma determinada linha de uma tabela.
  • 37.
    Aonde está operaçãodeve ser codificada ?
  • 38.
    public void atualiza(Contato c) { String sql = "update contato set nome=?, email=? where id = ?"; try { PreparedStatement stmt = conn.prepareStatement(sql); stmt.setString(1, c.getNome()); stmt.setString(2, c.getEmail()); stmt.setLong(3, c.getId()); stmt.execute(); stmt.close(); } catch (SQLException u) { throw new RuntimeException(u); } } Inseri o método atualiza na classe ContatoDAO.
  • 39.
    Mas como vouchamar esta operação ?
  • 40.
    public class ContatoTableModel extendsAbstractTableModel implements TableModelListener { private List<Contato> contatos; private List<String> colunas; private ContatoDAO dao; public ContatoTableModel(ContatoDAO dao){ this.dao = dao; this.contatos = dao.recupera(); colunas = Arrays.asList("Nome", "Email"); this.addTableModelListener(this); } …. } Precisamos tratar o evento “TableChange”. Para isso fazemos a seguinte modificação a classe ContatoTableModel
  • 41.
    public void tableChanged(TableModelEventevent) { int i = event.getFirstRow(); Contato contato = contatos.get(i); System.out.println(i); dao.atualiza(contato); } Então codificamos o método tableChanged da classe ContatoTableModel
  • 42.
  • 43.
    Se eu quisesseincluir um combo box? É possível ?
  • 44.
    Sim. Veja oseguinte exemplo. Adicione a coluna “grupo” a tabela contato. alter table contato add grupo varchar(50);
  • 45.
    Modifique as classesContato, ContatoDAO e ContatoTableModel para incluir mais uma coluna.
  • 46.
    public FrameTable (){ super("Teste"); finalContatoDAO dao = new ContatoDAO(); ContatoTableModel tm = new ContatoTableModel (dao); JTable t = new JTable (tm); JComboBox comboBox = new JComboBox(); comboBox.addItem("Familia"); comboBox.addItem("Amigo"); comboBox.addItem("Conhecido"); t.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(comboBox)); JScrollPane scroll = new JScrollPane(); scroll.setViewportView(t); add(scroll); setSize(200, 180); } Crie a combo box e adicione-a na coluna.
  • 47.
    Legal. Mas sea tabela tivesse outros tipos de dados, por exemplo, boolean.
  • 48.
    alter table contatoadd ativo boolean; Adicione a coluna ativo a tabela contato e modifique as classes Contato, ContatoDAO ....
  • 49.
    Mas a colunaativo mostra o valor false. Esse não é um valor esperado pelo usuário.
  • 50.
    A renderização padrãoda tabela é string, se quisermos usar outra precisamos informar o tipo de dado ao Jtable com o método getColumnClass. @Override public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); }
  • 51.
    O método getColumnClassfaz a JTable associar automaticamente um TableCellRenderer específico para campos booleanos. Por exemplo, booleano é renderizado como um checkbox.
  • 52.
    Se eu desejaradicionar ou remover uma linha ?
  • 53.
    Queria usar umbanco de dados mais simples, tipo o Access, ou seja, que não precise de um servidor.
  • 54.
    De fato, nemsempre precisamos de um banco de dados robusto em pequenas aplicações para desktop.
  • 55.
    Mesmo em aplicaçõesmais complexas, é comum usar um banco de dados mais simples no inicio do desenvolvimento. Depois, com o JDBC, podemos facilmente mudar para um servidor de banco de dados, como o Oracle ou mesmo o MySQL.
  • 56.
    Se eu desejaradicionar ou remover uma linha ?
  • 57.
    Basta adicionar umnovo contato a lista de contatos da ContatoTableModel e depois notificar esta mudança ao Jtable através do método: fireTableDataChanged.
  • 58.
    Porém, para salvarno banco de dados, precisamos adicioná-lo também ao banco.
  • 59.
    Então, fazemos assim,criamos um contato apenas com ID, e adicionamos a tabela. Então o usuário poderá atualiza-lo com as informações. Para isso criamos o seguinte método na classe ContatoTableModel. public void addContato(){ Contato c = new Contato () contatos.add(c); dao.adiciona(c); fireTableDataChanged(); }
  • 60.
    No construtor daclasse FrameTable adicione os botões adicionar e excluir: JPanel pan = new JPanel (); JButton btNovo = new JButton ("Novo"); JButton btExcluir = new JButton ("Excluir"); pan.add(btNovo, BorderLayout.EAST); pan.add(btExcluir, BorderLayout.EAST); add(pan, BorderLayout.SOUTH);
  • 61.
    Depois, basta adicionaro evento action com a seguinte codificação btNovo.addActionListener( new ActionListener () { @Override public void actionPerformed (ActionEvent ev){ tm.addContato(); } });
  • 62.
    Desafio: Codifiquem obotão excluir. Atividade