Neste artigo veremos como usar o JcomboBox com carregamento condicional, ou seja, como carregar os dados do componente de acordo com a escolha feita em um outro.
Um exemplo disso seria a escolha de um cliente no combobox 1 que carregaria os produtos deste cliente no combobox 2, que por sua vez a escolha do produto carregaria os tamanhos disponíveis no combobox 3. Este é um tipo de carregamento condicional, que está condicionado a escolha dos dados corretos.
A lógica que será ensina neste artigo aplica-se não apenas a Java Desktop, mas também para Java Web (JSF, por exemplo). A mesma técnica pode ser aplicada, apenas com a diferença nos recursos utilizados.
Carregamento Condicional
Criaremos um formulário usando o Netbeans que possuirá três combobox, como mostra a Figura 1.

O primeiro JcomboBox carregará todos os clientes disponíveis, o segundo carregará por padrão todos os produtos do primeiro cliente (que será o padrão ao abrir o formulário) e, por último, o combobox tamanho, que carregará todos os tamanhos do primeiro produto (que também será o padrão ao abrir o formulário).
Quando o usuário mudar o cliente, então os produtos mudarão e, para cada produto, os tamanhos também mudarão. Quando o usuário mudar o produto, então apenas os tamanhos serão alterados.
Para criar um formulário idêntico ao mostrado na Figura 1, podemos usar o arquivo “.form” da Listagem 1.
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.9"
type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation"
type="int" value="3"/>
</Properties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy"
type="int" value="1"/>
<SyntheticProperty name="generateCenter"
type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing"
type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName"
type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN"
type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode"
type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode"
type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget"
type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle"
type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal"
type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier"
type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2"
max="-2" attributes="0"/>
<Component id="jComboBoxCliente"
min="-2" pref="257" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0"
min="-2" max="-2" attributes="0"/>
<Component id="jComboBoxProduto"
alignment="0" min="-2" pref="257" max="-2" attributes="0"/>
<Component id="jLabel3" alignment="0"
min="-2" max="-2" attributes="0"/>
<Component id="jComboBoxTamanho"
alignment="0" min="-2" pref="257" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="131" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2"
attributes="0"/>
<EmptySpace type="unrelated" max="-2"
attributes="0"/>
<Component id="jComboBoxCliente" min="-2"
max="-2" attributes="0"/>
<EmptySpace min="-2" pref="27" max="-2"
attributes="0"/>
<Component id="jLabel2" min="-2" max="-2"
attributes="0"/>
<EmptySpace type="unrelated" max="-2"
attributes="0"/>
<Component id="jComboBoxProduto" min="-2"
max="-2" attributes="0"/>
<EmptySpace min="-2" pref="28" max="-2"
attributes="0"/>
<Component id="jLabel3" min="-2" max="-2"
attributes="0"/>
<EmptySpace type="unrelated" max="-2"
attributes="0"/>
<Component id="jComboBoxTamanho" min="-2" max="-2"
attributes="0"/>
<EmptySpace pref="65" max="32767"
attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel"
name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String"
value="Cliente"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox"
name="jComboBoxCliente">
<Events>
<EventHandler event="itemStateChanged"
listener="java.awt.event.ItemListener"
parameters="java.awt.event.ItemEvent"
handler="jComboBoxClienteItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox"
name="jComboBoxProduto">
<Events>
<EventHandler event="itemStateChanged"
listener="java.awt.event.ItemListener"
parameters="java.awt.event.ItemEvent"
handler="jComboBoxProdutoItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String"
value="Produto"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox"
name="jComboBoxTamanho">
</Component>
<Component class="javax.swing.JLabel"
name="jLabel3">
<Properties>
<Property name="text" type="java.lang.String"
value="Tamanho"/>
</Properties>
</Component>
</SubComponents>
</Form>Veja que precisamos de três classes para que nossos combobox's funcionem: Cliente, Produto e Tamanho.
package br.com.crudhibernate;
import java.util.List;
public class Cliente {
private int id;
private String nome;
private List<Produto> produtos;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public List<Produto> getProdutos() {
return produtos;
}
public void setProdutos(List<Produto> produtos) {
this.produtos = produtos;
}
@Override
public String toString(){
return this.nome;
}
}A classe cliente da Listagem 2 possui uma relação de produtos para todo Cliente. Além disso, adicionamos o método toString(), que servirá para mostrar o valor correto no ComboBox para assim vermos o nome do Cliente. Usaremos esta técnica para as outras classes.
package br.com.crudhibernate;
import java.util.List;
public class Produto {
private int id;
private String descricao;
private List<Tamanho> tamanhos;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public List<Tamanho> getTamanhos() {
return tamanhos;
}
public void setTamanhos(List<Tamanho> tamanhos) {
this.tamanhos = tamanhos;
}
@Override
public String toString(){
return this.id + " " + this.descricao;
}
}A classe produto da Listagem 3 tem uma relação de tamanhos associada a ela, e o seu método toString() é composto pela descrição e o id do produto (você entenderá mais à frente o porquê.
package br.com.crudhibernate;
public class Tamanho {
private int id;
private String descricao;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescricao() {
return descricao;
}
public void setDescricao(String descricao) {
this.descricao = descricao;
}
@Override
public String toString(){
return this.id + " " + this.descricao;
}
}Seguindo o mesmo princípio da classe Produto, a classe Tamanho da Listagem 4 também tem uma composição de valores no seu método toString().
Feito isso, vamos a construção do código do nosso formulário, chamado ComboBoxMain.java. Neste artigo não usaremos conexão com o banco de dados, pois nosso foco não é acrescentar complexidade a este ponto, então iremos popular os clientes manualmente, assim como os produtos e tamanhos. Vamos mostrar o código do formulário completo na Listagem 5 e explicar passo a passo seu funcionamento.
/*
* To change this license header, choose License
Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package br.com.crudhibernate;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author ronaldo
*/
public class ComboboxMain extends javax.swing.JFrame {
private List<Cliente> clientes = new ArrayList<Cliente>();
/**
* Creates new form ComboboxMain
*/
public ComboboxMain() {
initComponents();
init();
}
private void init(){
int cacheIdCliente = 1, cacheIdProduto = 1, cacheIdTamanho = 1;
String[] nomesClientes = new String[]{"Ronaldo",
"João", "David", "Marcos", "Maxwell", "Paulo"};
String[] nomesProdutos = new String[]{"Sapato A",
"Sapato B", "Sapato C"};
String[] nomesTamanhos = new String[]{"Pequeno",
"Medio", "Grande"};
for(int i = 0; i < nomesClientes.length; i++){
Cliente c = new Cliente();
c.setId(cacheIdCliente);
c.setNome(nomesClientes[i]);
c.setProdutos(new ArrayList<Produto>());
cacheIdCliente++;
for(int j = 0; j < nomesProdutos.length; j++){
Produto p = new Produto();
p.setId(cacheIdProduto);
p.setDescricao(nomesProdutos[j]);
p.setTamanhos(new ArrayList<Tamanho>());
cacheIdProduto++;
for(int k =0; k < nomesTamanhos.length; k++){
Tamanho t = new Tamanho();
t.setId(cacheIdTamanho);
t.setDescricao(nomesTamanhos[k]);
cacheIdTamanho++;
p.getTamanhos().add(t);
}
c.getProdutos().add(p);
}
clientes.add(c);
}
for(Cliente c : clientes){
jComboBoxCliente.addItem(c);
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
jComboBoxCliente = new javax.swing.JComboBox();
jComboBoxProduto = new javax.swing.JComboBox();
jLabel2 = new javax.swing.JLabel();
jComboBoxTamanho = new javax.swing.JComboBox();
jLabel3 = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jLabel1.setText("Cliente");
jComboBoxCliente.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jComboBoxClienteItemStateChanged(evt);
}
});
jComboBoxProduto.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jComboBoxProdutoItemStateChanged(evt);
}
});
jLabel2.setText("Produto");
jLabel3.setText("Tamanho");
javax.swing.GroupLayout layout = new javax.swing.
GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.
Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.
GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(jComboBoxCliente, javax.swing.
GroupLayout.PREFERRED_SIZE, 257, javax.swing.
GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2)
.addComponent(jComboBoxProduto, javax.swing.
GroupLayout.PREFERRED_SIZE, 257, javax.swing.
GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel3)
.addComponent(jComboBoxTamanho, javax.swing.
GroupLayout.PREFERRED_SIZE, 257, javax.swing.
GroupLayout.PREFERRED_SIZE))
.addContainerGap(131, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.
ComponentPlacement.UNRELATED)
.addComponent(jComboBoxCliente, javax.swing.
GroupLayout.PREFERRED_SIZE, javax.swing.
GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.
PREFERRED_SIZE)
.addGap(27, 27, 27)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.
ComponentPlacement.UNRELATED)
.addComponent(jComboBoxProduto, javax.
swing.GroupLayout.PREFERRED_SIZE, javax.
swing.GroupLayout.DEFAULT_SIZE, javax.swing.
GroupLayout.PREFERRED_SIZE)
.addGap(28, 28, 28)
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.
ComponentPlacement.UNRELATED)
.addComponent(jComboBoxTamanho, javax.swing.
GroupLayout.PREFERRED_SIZE, javax.swing.
GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.
PREFERRED_SIZE)
.addContainerGap(65, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
private void jComboBoxClienteItemStateChanged(java.awt.
event.ItemEvent evt) {
recarregarProdutos((Cliente) evt.getItem());
}
private void jComboBoxProdutoItemStateChanged(java.awt.
event.ItemEvent evt) {
recarregarTamanhos((Produto) evt.getItem());
}
private void recarregarProdutos(Cliente cliente){
jComboBoxProduto.removeAllItems();
for(Produto p : cliente.getProdutos()){
jComboBoxProduto.addItem(p);
}
recarregarTamanhos(cliente.getProdutos().get(0));
}
private void recarregarTamanhos(Produto produto){
jComboBoxTamanho.removeAllItems();
for(Tamanho t : produto.getTamanhos()){
jComboBoxTamanho.addItem(t);
}
}
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc="
Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available,
stay with the default look and feel.
* For details see
http://download.oracle.com/javase/tutorial/uiswing/
lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info :
javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(ComboboxMain.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(ComboboxMain.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(ComboboxMain.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(ComboboxMain.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ComboboxMain().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JComboBox jComboBoxCliente;
private javax.swing.JComboBox jComboBoxProduto;
private javax.swing.JComboBox jComboBoxTamanho;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
// End of variables declaration
}O primeiro passo é explicar como fizemos para popular os Clientes e seus respectivos produtos e os tamanhos de cada um. Para isso, criamos um método init() que fará tudo isso.
Olhando para o método init() da Listagem 5 podemos notar que temos três variáveis int logo de início:
int cacheIdCliente = 1, cacheIdProduto = 1, cacheIdTamanho = 1;Essas variáveis irão armazenar o id atual de cada objeto para que possamos incrementá-lo, apenas para maior controle. Esse id é importante porque usaremos o mesmo nome para produtos e tamanhos, e é apenas com esse ID que podemos distinguir que eles são objetos diferentes. Foram criados três arrays de String que armazenam os nomes dos clientes que serão criados, os produtos de cada cliente e os tamanhos de cada produto.
Cada cliente terá três produtos e cada produto terá três tamanhos, exatamente com o mesmo nome. Porém, sabemos que trata-se de produtos de outro cliente por conta do ID, e sabemos que trata-se de tamanhos de outro produto também pelo ID.
Com um laço for iterando entre o nome dos clientes começamos a criar o cliente sempre incrementando a variável cacheidcliente, como nas linhas 34 a 39.
É importante inicializar a propriedade setProdutos() para não termos um NullPointerException mais a frente. Ainda dentro do laço que faz a inserção do cliente, você fará a inserção dos produtos dentro do objeto “c”, que é o cliente atual (linhas 41 a 46).
Seguindo a mesma ideia o produto é criado, a lista de tamanhos é inicializada e o id do produto é incrementado. Em seguida criamos os tamanhos deste produto dentro do laço de produtos, como vemos nas linhas 48 a 52.
Agora começamos a fazer a associação entre as classes, visto que o tamanho é a última delas. Adicionamos o tamanho atual do objeto “t” dentro do produto atual “p':
p.getTamanhos().add(t);Depois, quando terminar a iteração nos tamanhos, adicionamos o produto atual dentro do cliente atual:
c.getProdutos().add(p);E por último, quando terminar a iteração nos produtos, adicionamos o cliente atual na lista de clientes, que é um atributo private no topo da classe.
clientes.add(c);Feito isto, o último passo é popular o combobox de clientes com a variável “clientes”, como vemos nas linhas 64 a 66.
Quando qualquer item for alterado no combobox cliente, um “reload” deve ser realizado nos outros dois combobox, através de um Listener. A ideal é adicionar um ItemListener ao combobox do cliente e fazer uma sobrescrita do método itemStateChanged(), mudando seu comportamento, como podemos ver nas linhas 89 a 93.
O método itemStateChanged() faz chamada para o método jComboBoxClienteItemStateChanged() através de um listener, onde este é disparado toda vez que o item do combobox for alterado. Quando o combobox do produto mudar usamos o mesmo processo, adicionando um listener (linhas 95 a 99).
O primeiro listener, jComboboxClienteItemStateChanged(), faz chamada ao método recarregarProdutos(), de acordo com as linhas 144 A 147.
Capturamos o item atualmente selecionado através do evt.getItem() e passamos para o método recarregarProdutos, que irá carregar o combobox de produtos de acordo com o cliente selecionado.
O método recarregarProdutos (linhas 152 a 158) primeiro remove todos os itens do combobox, para que não haja duplicação de valores ou valores anteriores que não são desejados atualmente. Posteriormente, fazemos uma iteração nos produtos do cliente atual e adicionamos um a um no jComboBoxProduto.
Ainda dentro do método recarregarprodutos() precisamos garantir também que os tamanhos sejam recarregados, e para fazer isso chamamos o método recarregarTamanhos(), passando o produto atual, que no caso será sempre o primeiro da lista.
O recarregamento dos tamanhos (linhas 160 a 165) segue o mesmo princípio do recarregamento de produtos, removendo todos os itens do combobox e depois adicionando um a um.
Temos agora nosso projeto pronto e funcionando, onde a cada mudança do usuário no combobox cliente ou produto, os itens são recarregados. O combobox de tamanho não precisa de recarrgamento ao mudar, pois ele é o último da hierarquia.
Neste artigo vimos como trabalhar com carregamento condicional em três combobox's através de listas populadas manualmente. Tal método pode ser aplicado sem problemas com dados do banco de dados, onde a única diferença será que no método de recarregarProdutos ou recarregarTamanhos você deverá popular com itens do banco de dados e no método init() também.