如果满足条件,则取消对JComboBox的选择更改(例如,对传入选择的验证)

时间:2012-05-22 15:45:58

标签: java swing events jcombobox itemlistener

我正在尝试动态验证JComboBox选择的项目,并且我想在验证不正确的情况下取消选择更改。有没有办法实现它?

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

我尝试定义一个包含旧值的var,取消注册侦听器,然后手动选择到先前的状态,但是第一次更改会出现问题,因为var没有初始化并且无法保存原始值

我也尝试过使用ActionListener,但发现无法以编程方式取消更改,而且我不需要fire事件然后没有更改但我正在评估手动设置setSelection的可能性,所以我恢复为ItemListener。

3 个答案:

答案 0 :(得分:5)

在初始方案中,当前一个选择不存在时,只需将其默认为默认选择索引,如0。

请参阅下面的示例代码:

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();
            }
        });
    }
}

第一次当textField不包含任何数据时,它只选择默认项,在这种情况下是第0个元素,你可以拥有它自己的。如果存在数据,则检查然后确定是否应该使用当前选择。

答案 1 :(得分:4)

我能做到这一点,不知道为什么你不能这样做。看看这个代码示例,选择三次任意值,然后在第四次它将恢复为空字符串:

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();
            }
        });
    }
}

具有以前值的代码

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();
            }
        });
    }
}

答案 2 :(得分:0)

实际上,没有办法阻止选择在JComboBox中进行更改。 之前的所有示例都没有真正阻止选择更改,而只是在选择更改后将其设置回先前选择的项目。

如果你看一下JTree,你会发现TreeWillExpandListener,它会让你有可能否决扩展,因为你会在它扩展之前收到TreeWillExpandEvent。

如果将ItemListener添加到JComboBox,您将在选择更改后收到ItemEvents。如果ItemEvent的stateChange是DESELECTED,那么getItem()将为您提供先前选择的项目。但是,如果你调用getSelectedItem(),它会给你另一个项目,因为选择已经改变了。