15 de agosto de 2010

JavaSE: CRUD em Swing

Neste post, iremos implementar parte do projeto do Hotel  da postagem: UML: Trabalhando com a diagramação . Este sistema será implementado em Java SE (para Desktop), com armazenamento em estruturas de dados (mais especificamente em java.util.List).
O sistema final terá a seguinte estrutura:
Obs: as classes do pacote model são as mesmas criadas na aula citada no link acima.
Mas, neste post será criado apenas o cadastro de Aposentos... então vamos lá!

Criando o projeto...
Neste projeto será utilizado o NetBeans, neste crie um novo projeto: Arquivo -  Novo Projeto - Java -  Aplicativo Java, e coloque o nome do projeto como: Hotel.

Criando o banco de dados...
Considerando que o pacote model já esteja implementado, vamos começar criando nossa classe que servirá de banco de dados, então dentro do pacote hotel, crie uma nova classe java chamada de BancoDados.java, com o seguinte codigo:
public class BancoDados {

    private static List<Aposento> aposentos = new ArrayList<Aposento>();
 
    /*
     * Aposentos
     */

    public static List<Aposento> getAposentos() {
        return aposentos;
    }

    public static void addAposento(Aposento aposento){
        aposentos.add(aposento);
    }

    public static void atualizaAposento(int linhaSelecionada, Aposento aposento){
        aposentos.set(linhaSelecionada, aposento);
    }

    public static void removeAposento(Aposento aposento){
        aposentos.remove(aposento);
    }
}
Perceba que nossos métodos são static, pois como instanciaremos apenas uma única vez nosso BancoDados, os mesmos precisarão ser acessados mas sem instanciar um novo BancoDados, isso será entendido melhor mais pra frente...

Tela inicial...
Ainda dentro do pacote hotel, crie um Formulário JFrame, chamado de Principal.java, este será nossa tela inicial do sistema. Por ser um JFrame o NetBeans dá a opção de criar a tela arrastando os componentes, então arraste um botão (JButton) para o formulário, este ficará com a seguinte aparência:

Chamando nossa tela principal...
Na classe Main.java que foi criada juntamente com o projeto, insira o seguinte codigo:
public class Main {

    public static void main(String[] args) {
       new BancoDados();

       JFrame principal = new Principal();
       principal.setVisible(true);
    }
}
perceba que nosso BancoDados está sendo instanciado, isso garante que ele seja inicializado junto com o sistema. E após ele, está sendo instanciado nosso formulário JFrame Principal.java, que é a tela inicial do sistema.
Para visualizar a aplicação, basta apertar a tecla F6 (padrão do NetBeans para executar a aplicação).

Criando a tela principal de aposentos
Agora crie um pacote chamado aposento, dentro do pacote hotel, naquele crie um novo formulário JFrame chamado Aposentos.java, arraste para a tela três botões (JButton) e uma tabela (JTable). Altere o nome das variáveis dos botões para: btnNovo, btnAlterar e btnRemover.

Para alterar os campos da tabela, clique nela com o botão direito e clique em conteúdo da tabela e vá na aba colunas, e edite as mesmas. Depois, clique novamente na tabela e vá em propriedades - aba código, e altere os modificadores de variáveis, o mesmo deve ficar como private static. Isso precisa ser feito para criamos um método estático de atualização da tabela, pois é o mesmo caso do BancoDados, mais pra frente precisaremos chamar este método sem instanciar um novo objeto Aposentos(). Então, no código fonte de Aposentos.java, insira o seguinte método(deve ficar dentro da classe):
public static void atualizaTabela(){
        DefaultTableModel tTabela = (DefaultTableModel) jTable1.getModel();
        tTabela.setNumRows(0);

        List<Aposento> aposentos = BancoDados.getAposentos();

        for (int linha = 0; linha < aposentos.size(); linha++)
        {
            Aposento aposento = aposentos.get(linha);

            tTabela.addRow(new Object[]{1});

            jTable1.setValueAt(aposento.getCodigo(), linha, 0);
            jTable1.setValueAt(aposento.getNumero(), linha, 1);
            jTable1.setValueAt(aposento.getDescricao(), linha, 2);
            jTable1.setValueAt(aposento.getValor(), linha, 3);
        }

    }
jTable1 é a minha tabela, caso esteja dando erro, verifique o nome da sua tabela.
Para que nossa tabela inicie atualizada, vamos chamar o método atualizaTabela() no construtor da classe Aposentos.java, ficando como o código abaixo:
public Aposentos() {
        initComponents();
        atualizaTabela();
    }

Agora iremos chamara tela de aposentos ao clicar no botão "Aposentos" na tela do frame Principal.java: então, em Principal.java de um duplo clique no botão "Aposentos" para que ele vá para o método do clique, onde será inserido o código para instanciar nosso frame Aposentos.java:
private void btnAposentosActionPerformed(java.awt.event.ActionEvent evt) {                                             
        JFrame aposentos = new Aposentos();
        aposentos.setVisible(true);
}    
No meu caso, eu alterei o nome da variável do meu botão para btnAposentos, por isso o nome do método inicia dessa forma.(isso vai ser de acordo com o nome dado ao botão aposentos)
Até este momento nossa aplicação já está abrindo a janela de aposentos ao clicar no botão "Aposentos" da tela inicial.

Tela de inserir aposento...
Dentro do pacote hotel.aposento crie um novo formulário JFrame com o nome de InserirAposento.java, crie a seguinte estrutura: quatro rótulos(JLabel), quatro campos de texto(JTextField) e dois botões (JButton)

Renomeie os nomes das variáveis dos campos de texto para: txtCodigo, txtNumero, txtDescricao, txtValor. E os botões para: btnOk, e btnCancelar.
Dê dois cliques no botão "Ok" para que ele vá para o método do clique do botão, e insira este codigo:
private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {                                         
        int iCodigo = Integer.parseInt(txtCodigo.getText());
        int iNumero = Integer.parseInt(txtNumero.getText());
        String sDescricao = txtDescricao.getText();
        double dValor = Double.parseDouble(txtValor.getText());
        Aposento aposento = new Aposento();
        aposento.setCodigo(iCodigo);
        aposento.setNumero(iNumero);
        aposento.setDescricao(sDescricao);
        aposento.setValor(dValor);

        BancoDados.addAposento(aposento);
        Aposentos.atualizaTabela();
        this.dispose();
    } 

Este método pega os valores dos campos, seta no objeto Aposento, e insere no nosso BancoDados, veja que não foi instanciado nenhum BancoDados aqui, lembre que se instancia apenas no Main.java. Depois que ele inserir, ele atualizará a tabela de aposentos pelo codigo Aposentos.atualizaTabela() que é o mesmo caso do BancoDados, e depois disto ele fecha a janela com o código this.dispose().
Agora dê um duplo clique no botão de cancelar:
private void btnCancelarActionPerformed(java.awt.event.ActionEvent evt) {                                         
    this.dispose();
}
Observe que o botão de cancelar, apenas fechará nossa janela.
Agora, iremos no Aposentos.java para chamar o InserirAposento. Então, vá em Aposentos.java e dê um duplo clique no botão "Novo":
private void btnNovoActionPerformed(java.awt.event.ActionEvent evt) {                                         
    JFrame janela = new InserirAposento();
    janela.setVisible(true);
}

Assim, nossa aplicação já está inserindo e listando os aposentos!

Alterando um aposento...
Para facilitar nossa implementação, ao invés de criar um novo JFrame para alterar o aposento, vamos copiar o InserirAposento.java e colar no mesmo pacote em que este se encontra, renomeando ele para AlterarAposento.java (ele vai pedir pra refatorar, então refatore!)
Vá para o código fonte do AlterarAposento.java e lá nas declarações dos atributos, declare os seguintes:
private Aposento aposento;
private int linhaSelecionada;
Logo abaixo do construtor do AlterarAposento.java, crie um novo construtor, passando um int por paramêtro, este int será a linha selecionada da tabela de Aposentos, que corresponde ao índice do aposento que foi selecionado na lista.
public AlterarAposento(int linhaSelecionada){
    initComponents();

    this.linhaSelecionada = linhaSelecionada;
    aposento = BancoDados.getAposentos().get(linhaSelecionada);
    codigo.setText(String.valueOf(aposento.getCodigo()));
    numero.setText(String.valueOf(aposento.getNumero()));
    descricao.setText(aposento.getDescricao());
    valor.setText(String.valueOf(aposento.getValor()));
}
Veja que estou setando a linhaSelecionada recebida por parâmetro na linhaSelecionada declarada na classe, pois esta será utilizada para setar o índice do objeto que será alterado na lista. A próxima linha: busca na lista do BancoDados o objeto Aposento daquela determinada linha. E quanto ao restante do código, estes setam os valores nos campos, para que ao abrir a janela, os campos estejam com os valores.
Agora dê um duplo clique no botão de Ok de AlterarAposento, perceba que este já está implementado pois foi copiado do inserir, então substitua o código pelo código a seguir:
private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {                                         
    int iCodigo = Integer.parseInt(codigo.getText());
    int iNumero = Integer.parseInt(numero.getText());
    String sDescricao = descricao.getText();
    double dValor = Double.parseDouble(valor.getText());
    aposento.setCodigo(iCodigo);
    aposento.setNumero(iNumero);
    aposento.setDescricao(sDescricao);
    aposento.setValor(dValor);

    BancoDados.atualizaAposento(linhaSelecionada, aposento);
    Aposentos.atualizaTabela();
    this.dispose();
}
Deixe a implementação do botão "Cancelar" como ele está.
Vá para o JFrame Aposentos.java e dê um duplo clique no botão "Alterar", implemente o mesmo da seguinte forma:
private void btnAlterarActionPerformed(java.awt.event.ActionEvent evt) {                                         
    int linhaSelecionada = jTable1.getSelectedRow();

    if (linhaSelecionada >= 0){
        JFrame janelaAlterar = new AlterarAposento(linhaSelecionada);
        janelaAlterar.setVisible(true);
    }
    else{
        JOptionPane.showMessageDialog(this, "É necessário selecionar um aposento", "Aposento", JOptionPane.INFORMATION_MESSAGE);
    }        
}     
Analisando o código: nosso int linhaSelecionada está recebendo o valor da linha selecionada da tabela. Aí esta linha é verificada, para não ocorrer de abrir a janela de alterar aposento sem ter uma linha selecionada na tabela, por isso do if e else, caso a linhaSelecionada seja maior ou igual a 0, significa que tem uma linha selecionada na tabela, então será aberto a janela de AlterarAposento passando por parâmetro o valor desta linha, senão, abre uma janela dizendo que é necessário selecionar um aposento para alterar!

Removendo um aposento...
Para o remover aposento não será necessário um novo JFrame, iremos criar um JOptionPane. Então dê um duplo clique no botão "Remover" e insira o seguinte código:
private void btnRemoverActionPerformed(java.awt.event.ActionEvent evt) {                                         
    int linhaSelecionada = jTable1.getSelectedRow();

    if (linhaSelecionada >= 0){
        int resposta = JOptionPane.showConfirmDialog(this, "Deseja excluir o aposento?");
        if (resposta == JOptionPane.YES_OPTION){
            Aposento aposento = BancoDados.getAposentos().get(linhaSelecionada);
            BancoDados.removeAposento(aposento);

            atualizaTabela();
        }
    }
    else{
        JOptionPane.showMessageDialog(this, "É necessário selecionar um aposento", "Aposento", JOptionPane.INFORMATION_MESSAGE);
    }
}
Analisando  o código: Veja que parte do código é bem parecida com o evento do botão "Alterar", mas ao invés de chamar um novo JFrame, é criada uma janela de diálogo, que recebe um valor inteiro que em seguida é verificado, caso tenha clicado em Yes, o código para a remoção do aposento é executado!
E assim termina nosso cadastro de aposento =)

13 comentários:

  1. Bela iniciativa,parabéns!

    ResponderExcluir
  2. No NetBeans dá erro no método

    public static void atualizaTabela()

    non-static variable jTable1 cannot be referenced from a static context

    Se tirar o static o método funciona, mas ai não é possível acessar este método de outras classes diretamente, como após inserir, atualizar...

    Parabéns pelo blog, eu e alguns amigos montamos um semelhante também, o Foo Java:

    foojava.blogspot.com

    Abracos

    Alguma sugestão?

    ResponderExcluir
  3. Problema resolvido, reli novamente todo o post para ver onde há diferencas com meu software e resolvi o problema alterando os modificadores das variáveis da jTable para private static:

    "Depois, clique novamente na tabela e vá em propriedades - aba código, e altere os modificadores de variáveis, o mesmo deve ficar como private static."

    Minha function eh um pouco diferente tambem...

    public static void mostrarProdutos(List resultList) {
    Vector< String > tableHeaders = new Vector< String >();
    Vector tableData = new Vector();
    tableHeaders.add("Codigo");
    tableHeaders.add("Nome");

    for(Object o : resultList) {
    Produto produto = (Produto)o;
    // cria linha
    Vector< Object > oneRow = new Vector< Object >();
    oneRow.add(produto.getProCodigo());
    oneRow.add(produto.getProNome());
    // add linha tabela
    tableData.add(oneRow);
    }
    tblDados.setModel(new DefaultTableModel(tableData, tableHeaders));
    }

    ResponderExcluir
  4. Como faço a mesma aplicação acima salvando em os dados do CRUD em arquivos .txt?

    ResponderExcluir
    Respostas
    1. Acho que isso pode te dar uma base de como fazer: http://www.javapractices.com/topic/TopicAction.do?Id=42

      Excluir
  5. Onde estõ as classes do model para eu copiar?

    ResponderExcluir
    Respostas
    1. Emir, as classes vc precisa montar a partir do diagrama de classes no projeto indicado no inicio da postagem, mas por dúvidas, segue o link: http://javasemcafe.blogspot.com.br/2010/08/uml-trabalhando-com-diagramacao.html

      Excluir
  6. Estou com problemas neste trecho o código:

    public class BancoDados {

    private static List aposentos = new ArrayList();

    /*
    * Aposentos
    */

    public static List getAposentos() {
    return aposentos;
    }

    public static void addAposento(Aposento aposento){
    aposentos.add(aposento);
    }

    public static void atualizaAposento(int linhaSelecionada, Aposento aposento){
    aposentos.set(linhaSelecionada, aposento);
    }

    public static void removeAposento(Aposento aposento){
    aposentos.remove(aposento);
    }
    }

    Exatamente nas linhas:

    aposentos.add(aposento);
    aposentos.set(linhaSelecionada, aposento);
    aposentos.remove(aposento);


    o add, set e remove são apresentados como erro.

    ResponderExcluir
    Respostas
    1. Veja se não tem alguma coisa a ver com os static

      Excluir
  7. Opa Andi blz, boa iniciativa, uma pergunta só vc parou o projeto nos aposentos, ou tem alguma outra postagem com hospede e contas, obrigado

    ResponderExcluir
    Respostas
    1. Olá, eu tinha feito o projeto inteiro (apenas com cruds), porém como já faz um tempo, não tenho mais o código fonte.

      Excluir
  8. Bom dia , que pena isso sera a minha ultima nota de de alg3... rs obrigado assim mesmo

    ResponderExcluir
  9. estou com problema nesta parte do código : List aposentos = BancoDados.getAposentos();

    eu uso o banco de dados mysql o que eu coloco no lugar de "BancoDados"??

    ResponderExcluir

Deixe seu comentário... ;)