user3660664
user3660664

Reputation: 247

Using multiple JComboBoxes; but they all get any action events

I'm sure that I'm doing something really stupid here; but it's been bugging me for hours. I'm using NetBeans 8.something, if that helps. I have a form with multiple combo boxes, to select from a data set. The first selects the year, this choice then populates monthCombo, the selection from which populates dayCombo, and so on.

The automatically generated code is here:

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 1323, Short.MAX_VALUE)
        .addGroup(jPanel1Layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(yearCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(monthCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(dayCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
    );

I've given them each a different ActionListener, like so:

    yearCombo.addActionListener(yearListener);
    monthCombo.addActionListener(monthListener);
    dayCombo.addActionListener(dayListener);

Where the listeners are defined like so:

    // -------------------------------------------------------
private ActionListener dayListener=new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {

        if(e.getModifiers()==CLICKED){
            log("Day combo item "+dayCombo.getSelectedItem().toString()+" source "+e.getSource().toString());
            rDataSelector.set(RDataSelector.SELECT_DAY,Integer.parseInt(dayCombo.getSelectedItem().toString()));
            rDataSelector.fillCombo(courseCombo);
        }
    }
};
// ---------------------------------------------------------------
private ActionListener monthListener=new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getModifiers()==CLICKED){
            log("Month combo item "+monthCombo.getSelectedItem().toString()+" source "+e.getSource().toString());
            rDataSelector.set(RDataSelector.SELECT_MONTH,Integer.parseInt(monthCombo.getSelectedItem().toString()));
            rDataSelector.fillCombo(dayCombo);
        }
    }
};
// -----------------------------------------------------------------
private ActionListener yearListener=new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getModifiers()==CLICKED){
            log("Year combo item "+yearCombo.getSelectedItem().toString());
            rDataSelector.set(RDataSelector.SELECT_YEAR,Integer.parseInt(yearCombo.getSelectedItem().toString()));
            rDataSelector.fillCombo(monthCombo);
        }
    }
};

FWIW, CLICKED is defined as 16, since that's what the event modifier is for a left mouse click.

The problem is that if I select, for example, an item from the yearCombo, all three ActionListeners are called.

This is the output from log() when the year item 2015 is clicked.

Year combo item 2015

Month combo item 2015 source javax.swing.JComboBox[,77,6,37x25,invalid,layout=javax.swing.plaf.basic.BasicComboBoxUI$Handler,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@1b2a5dc,flags=320,maximumSize=,minimumSize=,preferredSize=,isEditable=false,lightWeightPopupEnabled=true,maximumRowCount=8,selectedItemReminder=2015]

Day combo item 2015 source javax.swing.JComboBox[,120,6,37x25,invalid,layout=javax.swing.plaf.basic.BasicComboBoxUI$Handler,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@f77fca,flags=320,maximumSize=,minimumSize=,preferredSize=,isEditable=false,lightWeightPopupEnabled=true,maximumRowCount=8,selectedItemReminder=2015]

I know that I can get the source of the event, but this doesn't help, as there's no obvious way to tell them apart.

I can't believe that this is meant to work like this, so what am I doing wrong?

Upvotes: 0

Views: 46

Answers (1)

StanislavL
StanislavL

Reputation: 57421

On select in the year combo you fill the month combo so the event is fired. Accordingly selection changed so the dayCombo is populated firing the event.

There are 2 approachs:

  1. Define a flag isAPI. By default it's false. If your logic updates combo set it to true nd back t false after items update. All the listeners check the flag and it it's true (API call) just do nothing.

  2. Remove th listeners from the combox before updating their models and readd after the model is populated

Upvotes: 4

Related Questions