Java com café: Como vincular dados a um JComboBox

Como vincular dados a um JComboBox

Atualmente estou trabalhando num projeto no qual utilizo o framework JPA. Então a cada dia que passa eu acabo aprendendo algo novo sobre esta API e espero com essa experiência poder ajudar os que estão começando agora.
Hoje vou falar um pouco sobre como vincular dados que se encontram em uma tabela do banco a um componente JComboBox. A vinculação é simples de se fazer, mas a exibição da propriedade desejada é um pouco mais complicada como veremos adiante. Vou apresentar um passo a passo que traduzi do site netbeans.org, mas com algumas correções (o exemplo de código do site na parte "To render the combo box propertly" não funciona).
Vamos ao que interessa:

1. Clique com o botão direito no combo box e escolha Bind > elements (Vincular > elements). 

2. Clique em Import Data to Form (Importar dados para o Formulário...). Selecione a conexão e tabela que voce deseja vincular o combo box. Clique em OK. 

3. No combo From the Binding Source (Origem da vinculação), selecione o item que representa o result list da entidade. Por exemplo, se a entidade se chama Cliente.java, o objeto da lista deve ser gerado como clienteList

4. Deixe o valor em Binding Expression (Expressão de vinculação) como null e clique em OK. 

5. Clique com o botão direito no combo box novamente e escolha Bind > selectedItem (Vincular > selectedItem). Vincule a propriedade que será afetada pela selecão do usuário e clique em OK (normalmente o result list escolhido no passo 3). 

Até aqui já temos os dados vinculados ao combo box, porém se executar o programa verá que o combo mostrará dados da entidade selecionada convertida em String (objeto.toString()) e não uma propriedade específica:


Isto acontece porque, segundo o próprio site do NetBeans, a biblioteca Beans Binding não tem uma classe DetailBinding que permite especificar os valores exibidos no JComboBox.
Uma forma de resolver isto é escrever um código personalizado para mostrar a propriedade que queremos: 

1. Selecione o combo box

2. Na aba Propriedades da Janela de Propriedades, selecione a propriedade render

3. Clique no botão ... 

4. No combo na parte superior do editor de propriedades, selecione Custom Code (Código personalizado). 

5. Na área de texto, entre com um código parecido com o que segue abaixo onde Usuario é o nome da sua entidade e getUsuario é a propriedade que retorna o valor a ser vinculado. 

new DefaultListCellRenderer() {

    @Override
    public Component getListCellRendererComponent(
            JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
        super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
        if (value instanceof Usuario) {
            Usuario usuario = (Usuario) value;
            setText(usuario.getUsuario());
        }
        return this;
    }
}
Feito isso, o valor selecionado deverá aparecer no combo:


Uma outra abordagem mais simples para resolver o problema é sobrescrever o método toString da entidade em questão:

    @Override
    public String toString() {
        return getUsuario();
    } 

Basta fazer com que o método retorne o valor que você deseja mostrar no combo box. É isso aí! Espero que tenham gostado.

34 comentários:

  1. Ate ai eu consegui.. o problema é que variavel que recebe é do tipo Sala.

    Criei uma classe sala , e na classe turma coloquei um atributo do tipo sala...
    Na hora de cadastrar a turma...todos os registros de sala do banco vai para o jcombobox...
    e na hora de pegar os valores ele pede valor do tipo sala e o que sai do Jcombobox é string ou inteiro... HELP!

    ResponderExcluir
    Respostas
    1. Oi Nara, primeiramente é bom que você verifique se algum item está selecionado:

      cbEtapa.getSelectedItem() != null

      Depois você pode fazer o cast do item:

      sala = (Sala) comboSalas.getSelectedItem()

      Eu costumo fazer isso de uma vez só usando o operador ternário:

      turma.setSala(comboSalas.getSelectedItem() != null ? (Sala) cbEtapa.getSelectedItem() : null);

      Excluir
  2. Oi, estou criando um sistema para um Cinema usando dois formulário, um sobre Filme e outro sobre a Sessão que o filme vai ser exibido , em um formulário eu cadastro as informações do filme e exibo as informações em uma jTable, eu gostaria de saber como faço para aparecer no jComboBox do formulário de cadastro da Sessão as informações cadastradas no formulário Filmes (por exemplo o Titulo do Filme)

    Desde já Agradeço

    Crystyan

    ResponderExcluir
    Respostas
    1. Crystyan, estas informções sobre o filme estão apenas na jTable? Se for o caso você pode usar um método e passá-las como parâmetro. Mas o correto seria você salvar as informações num banco de dados e recuperá-las no formulário que precisar.

      Excluir
  3. Oi, sou novo em Java e estou fazendo um trabalho para faculdade. Preciso criar um combo que mostra as marcas de veiculos cadastradas.
    Minha tabela possui id e marca: ex.:
    id Marca
    1 GM
    2 Fiat
    3 Ford

    Eu quero mostrar no jCombobox a marca, mas quando o usuario selecionar, eu quero saber qual é o id.
    Para que eu possar pesquisar em outra tabela por este id.
    Em .net tem o selectedValue (id) e seletecItem (marca). Mas não encontrei no jCombobox. Como posso conseguir isto?

    ResponderExcluir
    Respostas
    1. Olá, para conseguir isto você precisa criar uma classe cujo nome poderia ser "Veiculo". Nesta classe você define os atributos id e marca juntamente com os métodos getters e setters. Ainda nesta classe, sobrescreva o método toString fazendo-o retornar a marca (para ser exibida no combo).
      Feito isto basta você criar objetos do tipo "Veiculo" e adicionar no combo. Quando o usuário selecionar, converta o item selecionado para "Veiculo" e recupere o id.

      Excluir
    2. Boa noite, Cara tenho a mesma duvida do amigo acima, porém no meu caso eu usarei um cb dinamico com os dados do banco. Porém so consigo listar o nome da marca e não consigo vincular o código. Segue o código se puder me ajudar.
      List listaMarca = new ArrayList();
      listaMarca = cd.listarTodos();

      int i = 0;
      for (MarcaBean cb : listaMarca) {
      cbMarca.addItem(cb);
      i++;
      }

      Excluir
  4. Muito obrigado por compatilhar essa informação amigo,me ajudou muito.

    ResponderExcluir
  5. Amigo, fiz a vinculação de dados, só que em um Jtable, só estou tendo o problema de aparecer o id em campos de chave estrangeira, como faço pra aparecer o nome em vez do Id?

    ResponderExcluir
    Respostas
    1. Rafael, neste caso você deve criar uma view em seu banco de dados fazendo a junção das tabelas e retornando os dados que deseja exibir na tabela.

      Excluir
  6. Parabéns Márcio Júnior, muito bom o tutorial!
    tentei usar aqui e tive o seguinte problema de compatibilidade
    incompatible types
    required: JComboBox
    found:
    segui os passos conforme o tutorial, esse é o único problema apresentado, pega os dados da entidade tranquilo, mais na hora que ponho o código para ele me trazer os valores acontece isso ae!

    tem ideia de onde posso estar errando?
    agradeço desde já!

    ResponderExcluir
    Respostas
    1. Marcio, me envie o trecho do seu código que está causando erro.

      marciosouzajunior@gmail.com

      Excluir
    2. private void initComponents() {
      bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

      entityManager = java.beans.Beans.isDesignTime() ? null : javax.persistence.Persistence.createEntityManagerFactory("db_estetica.fdbPU").createEntityManager();
      categoriaQuery = java.beans.Beans.isDesignTime() ? null : entityManager.createQuery("SELECT c FROM Categoria c");
      categoriaList = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : categoriaQuery.getResultList();
      categoriaQuery1 = java.beans.Beans.isDesignTime() ? null : entityManager.createQuery("SELECT c FROM Categoria c");
      categoriaList1 = java.beans.Beans.isDesignTime() ? java.util.Collections.emptyList() : categoriaQuery1.getResultList();
      jPanel1 = new javax.swing.JPanel();
      jLabel1 = new javax.swing.JLabel();
      jLabel2 = new javax.swing.JLabel();
      jComboBox1 =
      new DefaultListCellRenderer() {//o //netbeans fala que o erro ocorre aqui nessa linha
      //na janela de erros aparece o seguinte:
      //
      //incompatible types
      // required: JComboBox
      // found: anonymous DefaultListCellRenderer

      @Override
      public Component getListCellRendererComponent(
      JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
      super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
      if (value instanceof Categoria) {
      Categoria categoria = (Categoria) value;
      setText(categoria.getCategoria());
      }
      return this;
      }
      } ;


      desculpa a demora no retorno, mandei o codigo completo do frame que estou usando.

      OBG

      Excluir
  7. Márcio, muito obrigado! Eu tentei pelo site do netbeans e não consegui!
    Fico feliz pela atitude de nos ajudar! Parabéns dnovo!

    ResponderExcluir
    Respostas
    1. Valeu pelo comentário Jefferson! Ajude alguém quando você puder também..

      Excluir
  8. Olá não estou conseguindo achar onde devo escrever o fragmento de código para poder exibir o nome que esta no banco de dados ao invés dos dados inciais da vinculação , podes me ajudar? agradeço desde já
    Att .. Fernando

    ResponderExcluir
    Respostas
    1. Fernando, você tem uma classe model? Se tiver basta sobrescrever o método toString e fazê-lo retornar a descrição.

      Excluir
    2. Obrigado consegui!!
      Parabéns pela atitude e pelo conhecimento..
      Você saberia me explicar como eu posso fazer para atualizar uma JList em tempo real ? Eu usei a mesma forma que você explicou com o combobox usei em uma Jlist agora preciso que ela atualize em tempo real logo que eu insira os dados no banco.. Agradeço a força! e Parabéns novamente

      Excluir
    3. Você deve atualizar sua lista quando fizer alguma operação no banco.

      Excluir
    4. Como você está trabalhando no banco? Está usando algum framework?

      Excluir
    5. Não não , eu só adaptei o exemplo que você passou da ComboBox para a Jlist usei a vinculação e só ele demonstra os dados certinhos mas para demonstrar novos dados necessita reiniciar a aplicação ..

      Excluir
    6. Bom, isso depende da forma como você implementou e sem saber mais detalhes fica complicado te dar um exemplo. Se quiser pode entrar em contato pelo meu e-mail que farei o possível pra te ajudar.

      Excluir
    7. Beleza! Muito Obrigado Pela força e parabéns!

      Excluir
  9. Boa tarde Márcio Júnior!!

    Estou com um problema em setar o item (setSelectedItem) após a informação ja estar gravada no banco. Meu jComboBox recebe um objeto (Fornecedor no caso) com os atributos id e descrição. Quanto a gravação do id no banco está tudo certo. Meu problema é na hora de setar a opção na combo de acordo com esse id cadastrado no banco!! Tentei passar o objeto referente ao que quero selecionar na combo com o setSelectedItem, porém não obtive exito. O objeto está com os atributos corretos, porém não seta o valor na combo. Podes me ajuda??

    ResponderExcluir
    Respostas
    1. Você tem que adicionar todos fornecedores que estão no banco e depois usar o setSelectedItem passando o objeto.

      Excluir
  10. Fiz os dois métodos, um deu erro e o outro mostrou o projeto mas não adiantou, pois continuou mostrando a lista em string, o override. Teria a possibilidade de me ajudar?

    ResponderExcluir
    Respostas
    1. Olá! Desculpe pela demora em responder mas se ainda estiver com problemas entre em contato comigo no e-mail marciosouzajunior@gmail.com

      Excluir
  11. Boa tarde Marcio. Estou com dificuldades na hora de salvar data. O que acontece é que o jFormatted que está vinculado ao jTable com 'value', mas não aparece no jTable, quando digito a data no jFormatted e não salva no meu banco de dados, você poderia me ajudar por favor?

    ResponderExcluir
    Respostas
    1. Olá, peço que entre em contato comigo no e-mail marciosouzajunior@gmail.com

      Excluir
  12. Muito boa explicação. Funcionou de primeira.

    ResponderExcluir
  13. boas, não percebi o passo 5, quando clico em Custom Code aparece uma caixa de texto para preencher: " jComboBox2.setRenderer( );
    não sei o que colocar

    ResponderExcluir
    Respostas
    1. Olá! Faça como neste exemplo: https://netbeans.org/images_www/articles/80/java/gui-binding/custom.png

      Excluir