Canceling selection change on a JComboBox if condition is satisfied (e.g validation on the incoming selection)
Asked Answered
B

3

6

I´m trying to validate dynamically an item selected by a JComboBox, and I want to cancel the selection change in case the validation is not correct. Is there any way to achieve it?

private ItemListener itemListener = new ItemListener() {
    @Override                                            
    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            if (true) CANCEL_CHANGE;
        }
    }
};

I tried to define a var holding the old value, unregistering listener, and select to previous state manually, but then the problem comes with the first change, because the var is not initialized and there´s no way hold the original value.

I also tried using ActionListener, but found no way to programtically cancel the change, and I don´t need fire event then there´s no change but I am assessing the chance of setSelection manually, so I revert to ItemListener.

Boy answered 22/5, 2012 at 15:45 Comment(0)
S
4

I can do that, dunno why you cannot do it. Have a look at this code example, select three times any values, then on the fourth time it will revert back to empty string :

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

public class ComboTest {

    private JLabel imageLabel;
    private JComboBox comboImage;

    private String[] names = {"", "ukIcon","caIcon","unknwon"};
    private boolean flag;
    private int counter;

    public ComboTest(){
        flag = false;
        counter = 0;
        initComponents();
    }

    public void initComponents(){
        JFrame frame = new JFrame("Test Combo");        
        frame.setSize(320, 160);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        comboImage = new JComboBox(names);
        comboImage.addItemListener(new ItemListener(){
            public void itemStateChanged(ItemEvent event){
                if(event.getStateChange() == ItemEvent.SELECTED){
                    if (flag)
                        comboImage.setSelectedItem("");
                    else
                    {
                        counter++;
                        if (counter == 3)
                            flag = true;
                        System.out.println((String) comboImage.getSelectedItem());
                    }   
                }
            }
        });

        frame.add(comboImage);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ComboTest();
            }
        });
    }
}

Code with Previous Value

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

public class ComboTest {

    private JLabel imageLabel;
    private JComboBox comboImage;

    private String[] names = {"", "ukIcon","caIcon","unknwon"};
    private boolean flag;
    private int counter;
    private String previousValue;

    public ComboTest(){
        flag = false;
        counter = 0;
        previousValue = "";
        initComponents();
    }

    public void initComponents(){
        JFrame frame = new JFrame("Test Combo");        
        frame.setSize(320, 160);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        comboImage = new JComboBox(names);
        comboImage.addItemListener(new ItemListener(){
            public void itemStateChanged(ItemEvent event){
                if(event.getStateChange() == ItemEvent.SELECTED){
                    if (flag)
                        comboImage.setSelectedItem(previousValue);
                    else
                    {
                        counter++;
                        if (counter == 3)
                            flag = true;
                        previousValue = (String) comboImage.getSelectedItem();  
                        System.out.println((String) comboImage.getSelectedItem());
                    }   
                }
            }
        });

        frame.add(comboImage);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ComboTest();
            }
        });
    }
}
Spencer answered 22/5, 2012 at 15:58 Comment(4)
But does comboImage.setSelectedItem("") return to the previous selection? It sounds to me as it returns to default or first, but I´ll check and I answerBoy
@user1352530 what9s returns DESELECTED from ItemListenerDowntoearth
I don't understand... In my case adding setSelectedItem("") doesn't make it come back to previous state.Boy
Well seems to me you are writing if (true), this appears to me always true, when exactly is this condition false is something you have to look inside your Code and figure out the logic, or else post your Code, might be we can help :-)Spencer
T
5

In the initial scenario when previous selection is not present just default it to the default selection index, like 0.

See the sample code below:

import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;


import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class TestChangeListener {

    final JTextField jTextField = new JTextField(20);
    Object list[] = { "ItemA", "ItemB" };
    int oldSelectionIndex = -1;
    final JComboBox jComboBox = new JComboBox(list);

    void init() {
        JFrame jFrame = new JFrame("Test");
        JPanel jPanel = new JPanel();
        new TestChangeListener();
        jPanel.add(jTextField);
        jPanel.add(jComboBox);
        jFrame.add(jPanel);
        jComboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent event) {
                if (event.getStateChange() == ItemEvent.SELECTED) {
                    if (!"Okay".equalsIgnoreCase(jTextField.getText())) {
                        if (oldSelectionIndex < 0) {
                            jComboBox.setSelectedIndex(0);
                        } else {
                            jComboBox.setSelectedIndex(oldSelectionIndex);
                        }
                    } else {
                        oldSelectionIndex = jComboBox.getSelectedIndex();
                    }
                }
            }
        });
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
    }

    public static void main(String args[]) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new TestChangeListener().init();
            }
        });
    }
}

First time when textField doesnt contain any data, it just selects the default item, in this case its 0th element, you can have it your own. If data is present it checks and then decides if the current selection should be used or not.

Toomin answered 22/5, 2012 at 16:5 Comment(0)
S
4

I can do that, dunno why you cannot do it. Have a look at this code example, select three times any values, then on the fourth time it will revert back to empty string :

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

public class ComboTest {

    private JLabel imageLabel;
    private JComboBox comboImage;

    private String[] names = {"", "ukIcon","caIcon","unknwon"};
    private boolean flag;
    private int counter;

    public ComboTest(){
        flag = false;
        counter = 0;
        initComponents();
    }

    public void initComponents(){
        JFrame frame = new JFrame("Test Combo");        
        frame.setSize(320, 160);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        comboImage = new JComboBox(names);
        comboImage.addItemListener(new ItemListener(){
            public void itemStateChanged(ItemEvent event){
                if(event.getStateChange() == ItemEvent.SELECTED){
                    if (flag)
                        comboImage.setSelectedItem("");
                    else
                    {
                        counter++;
                        if (counter == 3)
                            flag = true;
                        System.out.println((String) comboImage.getSelectedItem());
                    }   
                }
            }
        });

        frame.add(comboImage);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ComboTest();
            }
        });
    }
}

Code with Previous Value

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

public class ComboTest {

    private JLabel imageLabel;
    private JComboBox comboImage;

    private String[] names = {"", "ukIcon","caIcon","unknwon"};
    private boolean flag;
    private int counter;
    private String previousValue;

    public ComboTest(){
        flag = false;
        counter = 0;
        previousValue = "";
        initComponents();
    }

    public void initComponents(){
        JFrame frame = new JFrame("Test Combo");        
        frame.setSize(320, 160);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        comboImage = new JComboBox(names);
        comboImage.addItemListener(new ItemListener(){
            public void itemStateChanged(ItemEvent event){
                if(event.getStateChange() == ItemEvent.SELECTED){
                    if (flag)
                        comboImage.setSelectedItem(previousValue);
                    else
                    {
                        counter++;
                        if (counter == 3)
                            flag = true;
                        previousValue = (String) comboImage.getSelectedItem();  
                        System.out.println((String) comboImage.getSelectedItem());
                    }   
                }
            }
        });

        frame.add(comboImage);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ComboTest();
            }
        });
    }
}
Spencer answered 22/5, 2012 at 15:58 Comment(4)
But does comboImage.setSelectedItem("") return to the previous selection? It sounds to me as it returns to default or first, but I´ll check and I answerBoy
@user1352530 what9s returns DESELECTED from ItemListenerDowntoearth
I don't understand... In my case adding setSelectedItem("") doesn't make it come back to previous state.Boy
Well seems to me you are writing if (true), this appears to me always true, when exactly is this condition false is something you have to look inside your Code and figure out the logic, or else post your Code, might be we can help :-)Spencer
P
0

In fact, there are no way to prevent selection to change in JComboBox. All previous examples does not really preventing selection change, instead they just setting selection back to previously selected item AFTER it was changed.

If you look at JTree, you will find TreeWillExpandListener, which will give you possibility to veto expanding, because you will receive TreeWillExpandEvent BEFORE it expands.

If you add ItemListener to JComboBox you will receive ItemEvents AFTER selection changed. If stateChange of ItemEvent is DESELECTED, then getItem() will give you previously selected item. However if you call getSelectedItem() it will give you another item, because selection is already changed.

Pieria answered 19/6, 2016 at 14:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.