Banco de dados + Swing em Java

17.201 visualizações

Publicada em

12 comentários
10 gostaram
Estatísticas
Notas
Sem downloads
Visualizações
Visualizações totais
17.201
No SlideShare
0
A partir de incorporações
0
Número de incorporações
84
Ações
Compartilhamentos
0
Downloads
1.115
Comentários
12
Gostaram
10
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Banco de dados + Swing em Java

  1. 1. Prof: Sérgio Souza Costa Banco de Dados + SWING em Java Usando o Controle JTable
  2. 2. 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
  3. 3. Aula de hoje • Inserir dados do banco de dados • Carregar dados do banco de dados • Conhecer o JTable e TableModel.
  4. 4. Inserindo dados ...
  5. 5. Cadastro de contatos • Montem a seguinte interface. • Alterem o nome das variáveis referentes as caixas de textos e botões. • Usem nomes sugestivos e sigam um “padrão”. Exemplo, btnCadastrar, btnLimpar, txtNome, txtEmail
  6. 6. Codifiquem a ação “Sair”, similar ao que fizemos na aulas sobre interface gráfica
  7. 7. Evitando fechamento acidental. Peça uma confirmação do usuário.
  8. 8. O Java oferece uma classe que cria este tipo de “caixas”, de mensagem, confirmação e entrada de usuário. private void btnSairActionPerformed(java.awt.event.ActionEvent evt) { int confirm = JOptionPane.showConfirmDialog (this, "Deseja Realmente fechar a aplicação?", "Sair - Confirmação", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (confirm == JOptionPane.YES_OPTION) { System.exit(1); } }
  9. 9. JOptionPane.showMessageDialog ( null, "Montando uma caixa de Dialogo sem ícone", "Mensagem", JOptionPane.PLAIN_MESSAGE ); int opcao = JOptionPane.showConfirmDialog ( null, "Deseja terminar ?", "Mensagem Final", JOptionPane.YES_NO_OPTION , JOptionPane.QUESTION_MESSAGE ) String numero=JOptionPane.showInputDialog ( null ,"Digite uma informação qualquer” ,"Entrada de dados", JOptionPane.QUESTION_MESSAGE );
  10. 10. Defina o “mnemonic” para cada botão. Facilita o uso direto pelo teclado.
  11. 11. Codifique a ação limpar, como fizemos em aula passada.
  12. 12. Codifique a ação cadastrar. No fim da ação, mostre uma mensagem para o usuário que foi salva com sucesso.
  13. 13. Vamos usar o banco de dados “contato”, o mesmo utilizado na aula sobre banco de dados.
  14. 14. Além disso, usaremos a mesma estrutura. As classes Contato e ContatoDao.
  15. 15. Contudo, faremos uma classe para abrir a conexão. A ConnectionFactory public class ConnectionFactory { public Connection getConnection() { try { return DriverManager.getConnection( "jdbc:mysql://localhost/Contato_bd", "root", "root"); } catch (SQLException e) { throw new RuntimeException(e); } } }
  16. 16. A ConnectionFactory será usada no construtor da ContatoDAO. public ContatoDAO() { connection = new ConnectionFactory().getConnection(); }
  17. 17. Depois de testado o aplicativo, substitua o textfield do telefone por um formattedtextfield.
  18. 18. Inclua os imports ao codigo fonte e codigo para configurar a mascara em personalizar codigo. MaskFormatter mascara; try { mascara = new MaskFormatter( "(##)####-####"); mascara.setPlaceholderCharacter('_'); fmttxtFone.setFormatterFactory ( new DefaultFormatterFactory(mascara)); } catch (ParseException ex) { } import javax.swing.text.DefaultFormatterFactory; import javax.swing.text.MaskFormatter;
  19. 19. Carregando dados ...
  20. 20. O desafio de hoje é conseguir carregar os dados de uma tabela e mostrar na interface gráfica.
  21. 21. 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; } Na atividade da aula 04, tinhamos implementando o método “recupera” da classe ContatoDAO que retorna a lista de contatos do banco de dados.
  22. 22. Eu vi que o Swing possui um controle gráfico, chamado JTable. Mas como faço para utilizá-lo ?
  23. 23. O Jtable apresenta uma grade multidimensional de objetos e é um dos controles mais complexos.
  24. 24. Porém, as tabelas são componentes inerentemente complexos, e o componente JTable oculta grande parte desta complexidade
  25. 25. 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
  26. 26. 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 );
  27. 27. Contudo, as tabelas podem ser dinâmicas e usadas de diferentes formas. Precisando ser mais versátil.
  28. 28. O Swing consegue isso implementando o Jtable como um componente MVC.
  29. 29. Como assim ?
  30. 30. O modelo (dados) é separado da vizualização. Model (TableModel ) View (JTable) JTable(TableModel dm)
  31. 31. Para problemas mais simples, existe o DefaultTableModel, que use um array bidimensional.
  32. 32. Lembra do código do slide 9 ? O codigo abaixo é equivalente. Nele mostro o uso explicito 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 );
  33. 33. Entendi, basta carregar os dados do banco, convertê-los para array, e construir um DefaultTableModel.
  34. 34. Calma, no caso de banco de dados esta não é a melhor solução.
  35. 35. Ao invés disso construimos nossa própria classe TableModel. Vamos ver melhor a camada modelo.
  36. 36. 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
  37. 37. 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 atribuirá 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
  38. 38. 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: Tipo Exibe como Imagem imagem Boolean checkBox (caixa de seleção) Object String
  39. 39. Visualização & 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
  40. 40. • 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 Trabalhando com a JTable: DefaultTableModel()
  41. 41. Trabalhando com a JTable: DefaultTableModel() 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 );
  42. 42. Vamos a prática
  43. 43. 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:
  44. 44. 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.
  45. 45. 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.
  46. 46. Este é o resultado do código anterior
  47. 47. Legal. Mas eu quero tornar o Jtable editável. Então, eu codifiquei o seguinte metodo para a classe “ContatoTableModel” @Override public boolean isCellEditable(int r, int c) { return true; }
  48. 48. Com este método Jtable passou me deixar alterar o valor, porém quando eu clico “enter” os valores não são alterados.
  49. 49. 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.
  50. 50. 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 ☹
  51. 51. Observe que o código não faz nenhuma alteração no banco de dados.
  52. 52. Qual operação SQL precisamos executar ?
  53. 53. A operação “Update ….” atualiza uma determinada linha de uma tabela.
  54. 54. Aonde está operação deve ser codificada ?
  55. 55. public void atualiza (Contato c) { String sql = "update contato set nome=?, email=? where id = ?"; try { PreparedStatement stmt = connection.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.
  56. 56. Mas como vou chamar esta operação ?
  57. 57. 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
  58. 58. 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
  59. 59. YES. Agora sim
  60. 60. Se eu quisesse incluir um combo box? É possível ?
  61. 61. Sim. Veja o seguinte exemplo. Adicione a coluna “grupo” a tabela contato. alter table contato add grupo varchar(50);
  62. 62. Modifique as classes Contato, ContatoDAO e ContatoTableModel para incluir mais uma coluna.
  63. 63. 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.
  64. 64. Legal. Mas se a tabela tivesse outros tipos de dados, por exemplo, boolean.
  65. 65. alter table contato add ativo boolean; Adicione a coluna ativo a tabela contato e modifique as classes Contato, ContatoDAO ....
  66. 66. Mas a coluna ativo mostra o valor false. Esse não é um valor esperado pelo usuário.
  67. 67. 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(); }
  68. 68. O método getColumnClass faz a JTable associar automaticamente um TableCellRenderer específico para campos booleanos. Por exemplo, booleano é renderizado como um checkbox.
  69. 69. Se eu desejar adicionar ou remover uma linha ?
  70. 70. Queria usar um banco de dados mais simples, tipo o Access, ou seja, que não precisasse de um servidor.
  71. 71. De fato, nem sempre precisamos de um banco de dados robusto em pequenas aplicações para desktop.
  72. 72. 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.
  73. 73. Então eu posso usar o Access da Microsoft ?
  74. 74. Sim, mas o melhor é deixar sua aplicação mais portável, funcionando em diferentes sistemas operacionais.
  75. 75. Existem soluções mais portáveis, um exemplo é o HSQL que é desenvolvido em JAVA.
  76. 76. Se eu desejar adicionar ou remover uma linha ?
  77. 77. 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.
  78. 78. Porém, para salvar no banco de dados, precisamos adiciona-lo também ao banco.
  79. 79. 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(); }
  80. 80. 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);
  81. 81. Depois, basta adicionar o evento action com a seguinte codificação btNovo.addActionListener( new ActionListener () { @Override public void actionPerformed (ActionEvent ev){ tm.addContato(); } });
  82. 82. Desafio: Codifiquem o botão excluir.

×