2

我的代码实际上很简单。我从这篇文章中看到了一个简单且类似的代码。

起初,我有 1 个组合框。我有一个名为itemStateChanged()的侦听器。我添加到这个监听器的目的是:“当用户从其保管箱中单击(选择)一个项目时执行一些代码”。

Cmb_ItemCategory = new javax.swing.JComboBox();

Cmb_ItemCategory.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Loading..." }));

Cmb_ItemCategory.addItemListener(new java.awt.event.ItemListener() {
    public void itemStateChanged(java.awt.event.ItemEvent evt) {
        Cmb_ItemCategoryItemStateChanged(evt);
    }
});

private void Cmb_ItemCategoryItemStateChanged(java.awt.event.ItemEvent evt) {

        if(evt.getStateChange() == java.awt.event.ItemEvent.SELECTED){
        System.err.println("Sombody click or change my model content");
        }

    }

在代码后面,我抓取了一些数据,然后调用了 removeAllItems() 方法。然后我在其中设置了一个新模型(来自新数据)。

-- at another line of code ---
Cmb_ItemCategory.removeAllItems();
Cmb_ItemCategory.setModel(newModel);

我意识到当我执行removeAllItem()方法时,我的itemStateChanged() 被调用。调用一次。

那么,如何使其仅在用户单击(选择)时才被调用,而不是在 removeAllItems() 调用时调用?

它类似于这篇文章。但这不是删除Items 的情况。CMIIW。

4

5 回答 5

5

在这里检查这段代码,它完美无缺,可能是你在调用的地方做错了什么removeAllItems()

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

public class ComboState 
{
    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("Combo State Testing : ");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JComboBox cbox = new JComboBox();
        cbox.addItem("One");
        cbox.addItem("Two");
        cbox.addItem("Three");
        cbox.addItem("Four");
        cbox.addItemListener(new ItemListener()
        {
            public void itemStateChanged(ItemEvent ie)
            {
                if (ie.getStateChange() == ItemEvent.SELECTED)
                {
                    System.out.println("Item Selected is : " + ie.getItem());
                }
                /*else
                {
                    System.out.println("I am called for other reasons.");
                }*/
            }
        });

        /*
         * Click me to remove JComboBox's items.
         */
        JButton removeButton = new JButton("REMOVE");
        removeButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                cbox.removeAllItems();
            }
        });

        frame.add(cbox, BorderLayout.CENTER);
        frame.add(removeButton, BorderLayout.PAGE_END);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new ComboState().createAndDisplayGUI();
            }
        });
    }
}
于 2012-04-18T06:00:13.890 回答
3

正如 nIcE cOw 已经在他的示例中说明的那样,当您使用 a 时它肯定可以工作DefaultComboBoxModel(在他的示例代码中就是这种情况,尽管它发生在屏幕后面)。

我可以解释您遇到的非DefaultComboBoxModel案例行为,尽管您的代码片段建议您使用一种。查看源代码是否JComboBox#removeAllItems存在不同的代码路径,因为该removeAllElements方法不是MutableComboBoxModel接口的一部分

public void removeAllItems() {
    checkMutableComboBoxModel();
    MutableComboBoxModel<E> model = (MutableComboBoxModel<E>)dataModel;
    int size = model.getSize();

    if ( model instanceof DefaultComboBoxModel ) {
        ((DefaultComboBoxModel)model).removeAllElements();
    }
    else {
        for ( int i = 0; i < size; ++i ) {
            E element = model.getElementAt( 0 );
            model.removeElement( element );
        }
    }
    selectedItemReminder = null;
    if (isEditable()) {
        editor.setItem(null);
    }
}

因此,使用 non-DefaultComboBoxModel您将一项一项删除项目。这意味着在某个时间点,您将删除选定的元素。您的模型的可能实现可能会在此时更改所选元素。如果您查看示例中的实现DefaultComboBoxModel(尽管不会触发此代码),您可以清楚地看到它更改了选择。

public void removeElementAt(int index) {
    if ( getElementAt( index ) == selectedObject ) {
        if ( index == 0 ) {
            setSelectedItem( getSize() == 1 ? null : getElementAt( index + 1 ) );
        }
        else {
            setSelectedItem( getElementAt( index - 1 ) );
        }
    }

    objects.removeElementAt(index);

    fireIntervalRemoved(this, index, index);
}

也许你的模型做了类似的事情,这解释了这个事件。DefaultComboBoxModel#removeAllElements只是为了使这篇文章完整,您可以清楚地看到它后面的代码将选择设置为null而不选择另一个对象。该代码中唯一奇怪的是它不会DESELECTED首先触发事件,尽管您知道如果您侦听该intervalRemoved事件,则选择已更改……但这与您的问题并不真正相关

public void removeAllElements() {
    if ( objects.size() > 0 ) {
        int firstIndex = 0;
        int lastIndex = objects.size() - 1;
        objects.removeAllElements();
        selectedObject = null;
        fireIntervalRemoved(this, firstIndex, lastIndex);
    } else {
        selectedObject = null;
    }
}

所以总结一下:我说您的问题的解决方案位于您的模型中,而不是您发布的代码中

于 2012-04-18T06:09:54.200 回答
2

一种快速的方法是在调用 removeAllItem() 之前将 bool 设置为 true 并在之后返回 false。仅当 bool 变量为 false 时才执行 itemStateChanged() 中的代码。

理想情况下,您可以覆盖 removeAllItem() 函数。

于 2012-04-18T04:28:14.610 回答
2

从整个讨论中不清楚,

  • 在删除所有项目之前,您必须从 JComboBox 中删除所有侦听器,在删除项目后,您可以重新添加侦听器,

  • 仍然不确定是否要动态添加和删除项目,或者您可以为另一个 JComponent 设置任何值,

  • (反对使简单的事情复杂化)你看到那里删除了吗,

.

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

public class ComboBoxTwo extends JFrame implements ActionListener, ItemListener {

    private static final long serialVersionUID = 1L;
    private JComboBox mainComboBox;
    private JComboBox subComboBox;
    private Hashtable<Object, Object> subItems = new Hashtable<Object, Object>();

    public ComboBoxTwo() {
        String[] items = {"Select Item", "Color", "Shape", "Fruit"};
        mainComboBox = new JComboBox(items);
        mainComboBox.addActionListener(this);
        mainComboBox.addItemListener(this);
        //prevent action events from being fired when the up/down arrow keys are used
        //mainComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
        getContentPane().add(mainComboBox, BorderLayout.WEST);
        subComboBox = new JComboBox();//  Create sub combo box with multiple models
        subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4
        subComboBox.addItemListener(this);
        getContentPane().add(subComboBox, BorderLayout.EAST);
        String[] subItems1 = {"Select Color", "Red", "Blue", "Green"};
        subItems.put(items[1], subItems1);
        String[] subItems2 = {"Select Shape", "Circle", "Square", "Triangle"};
        subItems.put(items[2], subItems2);
        String[] subItems3 = {"Select Fruit", "Apple", "Orange", "Banana"};
        subItems.put(items[3], subItems3);
//      mainComboBox.setSelectedIndex(1);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String item = (String) mainComboBox.getSelectedItem();
        Object o = subItems.get(item);
        if (o == null) {
            subComboBox.setModel(new DefaultComboBoxModel());
        } else {
            subComboBox.setModel(new DefaultComboBoxModel((String[]) o));
        }
    }

    @Override
    public void itemStateChanged(ItemEvent e) {
        if (e.getStateChange() == ItemEvent.SELECTED) {
            if (e.getSource() == mainComboBox) {
                if (mainComboBox.getSelectedIndex() != 0) {
                    FirstDialog firstDialog = new FirstDialog(ComboBoxTwo.this,
                            mainComboBox.getSelectedItem().toString(), "Please wait,  Searching for ..... ");
                }
            } 
        }
    }

    private class FirstDialog extends JDialog {

        private static final long serialVersionUID = 1L;

        FirstDialog(final Frame parent, String winTitle, String msgString) {
            super(parent, winTitle);
            setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
            JLabel myLabel = new JLabel(msgString);
            JButton bNext = new JButton("Stop Processes");
            add(myLabel, BorderLayout.CENTER);
            add(bNext, BorderLayout.SOUTH);
            bNext.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent evt) {
                    setVisible(false);
                }
            });
            javax.swing.Timer t = new javax.swing.Timer(1000, new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    setVisible(false);
                }
            });
            t.setRepeats(false);
            t.start();
            setLocationRelativeTo(parent);
            setSize(new Dimension(400, 100));
            setVisible(true);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new ComboBoxTwo();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
于 2012-04-18T08:16:39.767 回答
0

removeAllItems 方法没有调用 ItemStateChanged,但它调用了 actionPerformed,您可以通过运行以下简单代码来检查它:

public class Tuto {

    public static void main(String[] args) {
        //create the main frame
        JFrame frame = new JFrame();
        frame.setResizable(false);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setLayout(null);
        frame.setLocation(new Point(10, 10));
        frame.setPreferredSize(new Dimension(400, 300));

        JComboBox<String> combo = new JComboBox();
        combo.addItem("item 1");
        combo.addItem("item 2");
        combo.addItem("item 3");
        combo.setBounds(50, 30, 300, 20);
        combo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                System.out.println(" action Performed ");
            }
        });
        frame.add(combo);

        JButton button = new JButton("Remove");
        button.setBounds(50, 100, 100, 30);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                combo.removeAllItems();
            }
        });
        frame.add(button);

        frame.pack();
        frame.setVisible(true);
    }

}
于 2019-04-27T22:12:45.397 回答