简体   繁体   English

为什么JComboBox上的itemStateChanged在更改时被调用两次?

[英]Why is itemStateChanged on JComboBox is called twice when changed?

I'm using a JComboBox with an ItemListener on it. 我正在使用带有ItemListener的JComboBox。 When the value is changed, the itemStateChanged event is called twice. 更改值时,将调用itemStateChanged事件两次。 The first call, the ItemEvent is showing the original item selected. 第一个调用,ItemEvent显示所选的原始项目。 On the second time, it is showing the item that has been just selected by the user. 第二次,它显示用户刚刚选择的项目。 Here's some tester code: 这是一些测试人员代码:

public Tester(){

    JComboBox box = new JComboBox();
    box.addItem("One");
    box.addItem("Two");
    box.addItem("Three");
    box.addItem("Four");

    box.addItemListener(new ItemListener(){
        public void itemStateChanged(ItemEvent e){
            System.out.println(e.getItem());
        }
    });

    JFrame frame = new JFrame();
    frame.getContentPane().add(box);
    frame.pack();
    frame.setVisible(true);
}

So when I changed the Combo box once from "One" to "Three" the console shows: 因此,当我将组合框从“一”改为“三”时,控制台显示:

One
Three

Is there a way I can tell using the ItemEvent maybe, that it's the second item (ie. the user selected item)? 有没有一种方法我可以告诉使用ItemEvent,它是第二项(即用户选择的项目)? And if someone can explain why it gets called twice, that would be nice too! 如果有人可以解释为什么它被调用两次,那也会很好!

Thanks 谢谢

Have a look at this source: 看看这个来源:

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

public class Tester {

    public Tester(){

        JComboBox box = new JComboBox();
        box.addItem("One");
        box.addItem("Two");
        box.addItem("Three");
        box.addItem("Four");

        box.addItemListener(new ItemListener(){
            public void itemStateChanged(ItemEvent e){
                System.out.println(e.getItem() + " " + e.getStateChange() );
            }
        });

        JFrame frame = new JFrame();
        frame.getContentPane().add(box);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String [] args) {
        Tester tester = new Tester();
    }
}

Use the getStateChange to determine if an item is selected or deselected 使用getStateChange确定是选择还是取消选择项

According to this thread , 根据这个帖子

It gets tripped when you leave one result and then called again when set to another result 当你离开一个结果时它会被触发,然后在设置为另一个结果时再次被调用

Don't listen for itemStateChanged. 不要听itemStateChanged。 Use an ActionListener instead, which is good for handling events of the combo. 请改用ActionListener,这对处理组合事件很有用。
You need a ItemStateListener if you need to separately handle deselection / selection depending on the item involved. 如果需要根据所涉及的项目单独处理取消选择/选择,则需要ItemStateListener。

Changing the state of the item within itemStateChanged causes itemStateChanged to be fired... this called "reentrance". 更改itemStateChanged中项目的状态会导致itemStateChanged被触发...这称为“reentrance”。

I wanted to get the index string after selected and set in combobox 我想在选择后获取索引字符串并在组合框中设置

        comboBox1.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if(e.getStateChange() == ItemEvent.SELECTED) {
                    comboBox1ItemStateChanged();
                }
            }
        });

Yo can do it like this: 哟可以这样做:

import java.awt.event.*;

jComboBox1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("Hello");
        }
    });
private void dropDown_nameItemStateChanged(java.awt.event.ItemEvent evt) {                                                 


    if(evt.getStateChange() == ItemEvent.SELECTED)
    {
        String item = (String) evt.getItem();
        System.out.println(item);
    }

}

Good Luck! 祝好运!

The code is: 代码是:

public class Tester {

    private JComboBox box;

    public Tester() {

        box = new JComboBox();
        box.addItem("One");
        box.addItem("Two");
        box.addItem("Three");
        box.addItem("Four");

        box.addItemListener(new ItemListener() {

            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == 1) {

                    JOptionPane.showMessageDialog(box, e.getItem());
                    System.out.println(e.getItem());
                }
            }
        });

        JFrame frame = new JFrame();
        frame.getContentPane().add(box);
        frame.pack();
        frame.setVisible(true);
    }
}

Have a look here, 看看这里,

box.addItemListener(new ItemListener(){
    public void itemStateChanged(ItemEvent e){
        if(e.getStateChange()== ItemEvent.SELECTED) {
            //this will trigger once only when actually the state is changed
            JOptionPane.showMessageDialog(null, "Changed");
        }
    }
});

When you select a new option, it will only once call the JOptionPane, indicating that the code there will be called once only. 当您选择一个新选项时,它只会调用一次JOptionPane,表示那里的代码只会被调用一次。

Quote from Java Tutorial : 引用Java教程

"Only one item at a time can be selected in a combo box, so when the user makes a new selection the previously selected item becomes unselected. Thus two item events are fired each time the user selects a different item from the menu . If the user chooses the same item, no item events are fired." “在组合框中一次只能选择一个项目,因此当用户进行新选择时,先前选择的项目将被取消选中。 因此,每次用户从菜单中选择不同的项目时,将触发两个项目事件 。用户选择相同的项目,不会触发任何项目事件。“

  1. When the anyitem is selected from the combo box, it internally triggers selection change, ie it will call the function setSelectedItem. 当从组合框中选择anyitem时,它会在内部触发选择更改,即它将调用函数setSelectedItem。
  2. If an explicit itemStateChanged event listener is implemented, the setSelectedItem will call itemStateChanged. 如果实现了显式的itemStateChanged事件侦听器,则setSelectedItem将调用itemStateChanged。 So, when an item is selected it calls setSelectedItem then it calls itemStateChanged. 因此,当选择一个项目时,它会调用setSelectedItem,然后调用itemStateChanged。
  3. As the value of the combo box changes, even that too triggers itemStateChanged and hence itemStateChanged gets called. 随着组合框的值发生变化,即使这也会触发itemStateChanged,因此会调用itemStateChanged。
  4. I had written listener for item change to handle change in value of combo box when set internally from the code and that caused the function getting called twice. 我已经为项目更改编写了监听器,以便在从代码内部设置时处理组合框值的更改,并导致函数被调用两次。

Here are the 2 back traces, which gets invoked when a value is selected from combo box. 以下是2个后退跟踪,当从组合框中选择值时会调用它。

1st time on actual value change: 第一次实际价值变化:

dataMgr.MainInterface.jComboBoxPaymentStatusValueChangeHandle(MainInterface.java:1431), 
dataMgr.MainInterface.jComboBoxPaymentStatusItemStateChanged(MainInterface.java:1676), 
dataMgr.MainInterface.access$600(MainInterface.java:28), 
dataMgr.MainInterface$7.itemStateChanged(MainInterface.java:437), 
javax.swing.JComboBox.fireItemStateChanged(JComboBox.java:1223), 
javax.swing.JComboBox.selectedItemChanged(JComboBox.java:1271), 
javax.swing.JComboBox.contentsChanged(JComboBox.java:1330), 
javax.swing.AbstractListModel.fireContentsChanged(AbstractListModel.java:118), 
javax.swing.DefaultComboBoxModel.setSelectedItem(DefaultComboBoxModel.java:93), 
javax.swing.JComboBox.setSelectedItem(JComboBox.java:576), javax.swing.JComboBox.setSelectedIndex(JComboBox.java:622), javax.swing.plaf.basic.BasicComboPopup$Handler.mouseReleased(BasicComboPopup.java:852), java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:290), java.awt.Component.processMouseEvent(Component.java:6533), javax.swing.JComponent.processMouseEvent(JComponent.java:3324), javax.swing.plaf.basic.BasicComboPopup$1.processMouseEvent(BasicComboPopup.java:501), java.awt.Component.processEvent(Component.java:6298), java.awt.Container.processEvent(Container.java:2236), java.awt.Component.dispatchEventImpl(Component.java:4889), java.awt.Container.dispatchEventImpl(Container.java:2294), java.awt.Component.dispatchEvent(Component.java:4711), java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888), java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525), java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466), java.awt.Container.dispatchEventImpl(Container.java:2280), java.awt.Window.dispatchEventImpl(Window.java:2746), java.awt.Component.dispatchEvent(Component.java:4711), java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758), java.awt.EventQueue.access$500(EventQueue.java:97), java.awt.EventQueue$3.run(EventQueue.java:709), java.awt.EventQueue$3.run(EventQueue.java:703), java.security.AccessController.doPrivileged(Native Method), java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76), java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86), java.awt.EventQueue$4.run(EventQueue.java:731), java.awt.EventQueue$4.run(EventQueue.java:729), java.security.AccessController.doPrivileged(Native Method), java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76), java.awt.EventQueue.dispatchEvent(EventQueue.java:728), java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201), java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116), java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105), java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101), java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93), java.awt.EventDispatchThread.run(EventDispatchThread.java:82)]

2nd time from the due to operation on combobox 第二次从组合操作到操作

dataMgr.MainInterface.jComboBoxPaymentStatusValueChangeHandle(MainInterface.java:1431), 
dataMgr.MainInterface.jComboBoxPaymentStatusItemStateChanged(MainInterface.java:1676), 
dataMgr.MainInterface.access$600(MainInterface.java:28), 
dataMgr.MainInterface$7.itemStateChanged(MainInterface.java:437), 
javax.swing.JComboBox.fireItemStateChanged(JComboBox.java:1223), 
javax.swing.JComboBox.selectedItemChanged(JComboBox.java:1280), 
javax.swing.JComboBox.contentsChanged(JComboBox.java:1330), 
javax.swing.AbstractListModel.fireContentsChanged(AbstractListModel.java:118), 
javax.swing.DefaultComboBoxModel.setSelectedItem(DefaultComboBoxModel.java:93), 
javax.swing.JComboBox.setSelectedItem(JComboBox.java:576), 
javax.swing.JComboBox.setSelectedIndex(JComboBox.java:622), 
javax.swing.plaf.basic.BasicComboPopup$Handler.mouseReleased(BasicComboPopup.java:852), 
java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:290), 
java.awt.Component.processMouseEvent(Component.java:6533), 
javax.swing.JComponent.processMouseEvent(JComponent.java:3324), 
javax.swing.plaf.basic.BasicComboPopup$1.processMouseEvent(BasicComboPopup.java:501), 
java.awt.Component.processEvent(Component.java:6298), java.awt.Container.processEvent(Container.java:2236), 
java.awt.Component.dispatchEventImpl(Component.java:4889), java.awt.Container.dispatchEventImpl(Container.java:2294), 
java.awt.Component.dispatchEvent(Component.java:4711), java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888), 
java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525), java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466), 
java.awt.Container.dispatchEventImpl(Container.java:2280), java.awt.Window.dispatchEventImpl(Window.java:2746), 
java.awt.Component.dispatchEvent(Component.java:4711), java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758),
java.awt.EventQueue.access$500(EventQueue.java:97), java.awt.EventQueue$3.run(EventQueue.java:709), 
java.awt.EventQueue$3.run(EventQueue.java:703), java.security.AccessController.doPrivileged(Native Method),
java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76), 
java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86), 
java.awt.EventQueue$4.run(EventQueue.java:731), java.awt.EventQueue$4.run(EventQueue.java:729), 
java.security.AccessController.doPrivileged(Native Method), java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76), java.awt.EventQueue.dispatchEvent(EventQueue.java:728), java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201), java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116), java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105), java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101), java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93), java.awt.EventDispatchThread.run(EventDispatchThread.java:82)]

JComboBox.setFocusable(false)可以解决这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM