JCombobox, object changed only on second click (ItemListener)

39 Views Asked by At

i've some issue using listener to JCombobox. I have JCombobox with two CercleItemOption which is a composition of a JLabel and an object CercleSelection extending from JPanel. CercleSelection draws a circle with certain color.

So i'm using ItemListener to support the event. My goal is to print on frame the colored circle corresponding to the selected item.

import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;

public class PanneauSelection extends JPanel {

    private GridBagConstraints grid = new GridBagConstraints();

    public PanneauSelection(){
        super();
        init();
        setVisible(true);
    }

    private void init() {

        LineBorder lb;
        CompoundBorder cb;

        setLayout(new GridBagLayout());
        EmptyBorder eb = new EmptyBorder(5,10,5,10);

        grid.fill = GridBagConstraints.BOTH;
        grid.insets = new Insets(3,3,3,3);

        JLabel[] appLabel = {
                new JLabel("<html>Racc. <br/>Bac/conduite</html>", SwingConstants.CENTER),
                new JLabel("Vanne", SwingConstants.CENTER),
                new JLabel("Pompe", SwingConstants.CENTER),
                new JLabel("Turbine", SwingConstants.CENTER),
        };

        CercleSelection[] appCircle = {
                new CercleSelection(new Color(222, 146, 15)),
                new CercleSelection(Color.BLUE),
                new CercleSelection(new Color(67, 160, 53)),
                new CercleSelection(Color.RED),
        };

        DefaultListCellRenderer dlcr = new DefaultListCellRenderer();
        dlcr.setHorizontalAlignment(DefaultListCellRenderer.CENTER);

        JComboBox<CercleItemOption> optionList = new JComboBox<>();
        optionList.addItem(new CercleItemOption(new JLabel("Coude"), new CercleSelection(Color.cyan)));
        optionList.addItem(new CercleItemOption(new JLabel("Chgt de section"), new CercleSelection(Color.PINK)));
        optionList.setRenderer(dlcr);


        for(int i=0; i<appLabel.length; i++){
            grid.gridy = i;

            //First column
            grid.gridx = 0;
            lb = new LineBorder(appCircle[i].getCouleur(), 2, true);
            cb = new CompoundBorder(lb,eb);
            appLabel[i].setBorder(cb);
            add(appLabel[i], grid);

            //Second column
            grid.gridx = 1;
            appCircle[i].setBorder(eb);
            add(appCircle[i], grid);
        }

        grid.gridy = 4;
        grid.gridx = 0;
        add(optionList, grid);

        grid.gridx = 1;
        add(((CercleItemOption)optionList.getSelectedItem()).getCercle(), grid);

        optionList.addItemListener(itemEvent -> {
            setVisible(false);
            grid.gridx = 1;
            grid.gridy = 4;
            CercleItemOption cs = (CercleItemOption) itemEvent.getItem();
            add(cs.getCercle(), grid);
            revalidate();
            repaint();
            setVisible(true);
        });


        this.setBorder(new EmptyBorder(0,20,0,0));
    }


    public static void main(String[] args){
        JFrame f = new JFrame();
        f.add(new PanneauSelection());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

    }

}

I expected something like :
"coude" -> [Circle] cyan
"chgt de section" -> [Circle] pink

With my code color doesn't change on the first call of ItemListener, but only on the second one. Finally on second click, i have :
"coude" -> [Circle] pink
"chgt de section" -> [Circle] cyan

CercleItemOption class

    import javax.swing.*;

    public class CercleItemOption {
        private JLabel label;
        private CercleSelection cercle;

        public CercleItemOption(JLabel l, CercleSelection c){
            label = l;
            cercle = c;
        }

        @Override
        public String toString(){
            return label.getText();
        }

        public JLabel getLabel() {
            return label;
        }

        public CercleSelection getCercle() {
            return cercle;
        }
    }

CercleSelection class

import javax.swing.*;
import java.awt.*;

public class CercleSelection extends JPanel {

    public final static int TAILLE = 11;

    Color couleur;

    public CercleSelection(Color c){
        super();
        couleur = c;
        setSize(TAILLE,TAILLE);
        setVisible(true);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(couleur);
        //Draw in the middle
        g.fillOval(TAILLE/2,TAILLE/2,TAILLE,TAILLE);
    }

    public Color getCouleur() {
        return couleur;
    }

}

Thank you in advance for help

1

There are 1 best solutions below

0
Dalek On BEST ANSWER

For someone who have the same issue, the solution was to remove the existed component and replace it to the new one.

To get the actual component, i add a new variable.

Class PanneauSelection :

private CercleItemOption cercleSelectionne;

init() method :


private void init(){

     //...

     grid.gridy = 4;
     grid.gridx = 0;
     add(optionList, grid);
     grid.gridx = 1;
     cercleSelectionne = ((CercleItemOption) optionList.getSelectedItem());
     add(cercleSelectionne.getCercle(), grid);

     optionList.addItemListener(itemEvent -> {
                remove(cercleSelectionne.getCercle());
                grid.gridx = 1;
                grid.gridy = 4;
                cercleSelectionne = (CercleItemOption) itemEvent.getItem();
                add(cercleSelectionne.getCercle(), grid);
                revalidate();
                repaint();
     });

}