Stubborn JComboBox

时间:2012-01-04 16:19:31

标签: java swing jcombobox

我在下面的代码中显示了一个JComboBox。当程序启动时,actionPerformed事件立即触发,导致一些空指针异常,所以我想从没有选择的元素开始。但是,由于某些原因它不起作用(无论我做什么,它始终以显示“USD / TRY”开头)。任何人都有任何想法?

JComboBox comboBox = new JComboBox(new String[]{"USD/TRY", "EUR/TRY", "GBP/TRY"});

comboBox.setSelectedIndex(-1); // doesnt change anything
comboBox.setSelectedIndex(2); // doesnt change anything     
comboBox.setSelectedItem(null); // doesnt change anything

更新:构建如下所示的组合框不会改变任何内容

JComboBox comboBox = new JComboBox(); 

comboBox.addItem("USD/TRY"); 
comboBox.addItem("EUR/TRY"); 
comboBox.addItem("GBP/TRY"); 

这是SSCCE:

public class MainFrame {

    private final JTextArea textArea = new JTextArea();
    private IExchangeSource s;

    public MainFrame(final IExchangeSource s) {
        //build gui
        final JComboBox comboBox = new JComboBox();

        comboBox.addItem("USD/TRY");
        comboBox.addItem("EUR/TRY");
        comboBox.addItem("GBP/TRY");

        comboBox.setSelectedIndex(-1); // doesnt change anything
        //comboBox.setSelectedIndex(2); // doesnt change anything


        JFrame f = new JFrame("Currency Converter");
        JPanel p = new JPanel(new BorderLayout());
        textArea.setName("textarea");
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);
        this.s = s;

        comboBox.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                String exchange = (String) comboBox.getSelectedItem();

                s.getData(exchange);
            }
        });

        p.add(comboBox, BorderLayout.NORTH);
        p.add(textArea, BorderLayout.CENTER);
        f.setPreferredSize(new Dimension(300, 300));
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.add(p);
        comboBox.setSelectedIndex(0);
        f.setVisible(true);
    }
}

3 个答案:

答案 0 :(得分:7)

您的(不完整)示例调用

comboBox.setSelectedIndex(0);

在变为可见之前,取消之前的任何设置。在添加监听器之前设置所需的初始索引,并且不要忽略从EDT开始,如下面的sscce所示。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class MainFrame {

    private final JTextArea textArea = new JTextArea();


    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MainFrame();
            }
        });
    }
    public MainFrame() {
        //build gui
        final JComboBox comboBox = new JComboBox();

        comboBox.addItem("USD/TRY");
        comboBox.addItem("EUR/TRY");
        comboBox.addItem("GBP/TRY");

        JFrame f = new JFrame("Currency Converter");
        JPanel p = new JPanel(new BorderLayout());
        textArea.setName("textarea");
        textArea.setWrapStyleWord(true);
        textArea.setLineWrap(true);

        comboBox.setSelectedIndex(-1);
        comboBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(comboBox.getSelectedItem() + ": " + e);
            }
        });

        p.add(comboBox, BorderLayout.NORTH);
        p.add(textArea, BorderLayout.CENTER);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setSize(new Dimension(300, 300));
        f.add(p);
        f.setVisible(true);
    }
}

答案 1 :(得分:2)

1)添加ItemListener而不是ActionListener,但此ItemListener总是会触发两次事件SELECTEDDESELECTED

  myComboBox.addItemListener(new ItemListener() {

        @Override
        public void itemStateChanged(ItemEvent e) {
            if (e.getStateChange() == ItemEvent.SELECTED) {
                //some stuff
            }
        }
    });

2)您的GUI可能在EventDispashThread上创建,但在这种情况下并不重要,您必须通过包装到invokeLater()中来延迟此方法,例如

public class MainFrame {
     .
     .
     .

    f.setPreferredSize(new Dimension(300, 300));
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.pack();
    f.add(p);
    comboBox.setSelectedIndex(0);
    f.setVisible(true);
    selectDesiredItem();
}

private void selectDesiredItem() {
  EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            comboBox.setSelectedIndex(-1);
        }
    });  
}

3)更好的是货币对的实施AutoCompete JComboBox / JTextField

4)也许并不重要,但CcyPairs默认有四个方面

  • Buy BaseCcy

  • Sell BaseCcy

  • Buy VariableCcy

  • Sell VariableCcy

答案 2 :(得分:0)

到目前为止的建议都很好。但有时候,如果对构建组件的方式感到困惑,则需要更直接的修复:

  1. 子类JComboBox(或任何Swing类触发事件,JList等...)
  2. 添加字段private boolean fireEvents = false;考虑将其volatile
  3. 覆盖相关的fireXXX()方法以检查fireEvents的状态
  4. 仅在所有构造和初始化完成后设置fireEvents = true
  5. 如果稍后要求“大修”,例如在加载新文件,新设置时,您可以在重建所有内容时将fireEvents设置为false。