The Stubborn JComboBox

一曲冷凌霜 提交于 2019-12-05 14:32:26

Your (incomplete) example invokes

comboBox.setSelectedIndex(0);

right before becoming visible, canceling any previous setting. Set the desired initial index before adding the listener, and don't neglect to start on the EDT, as shown in the sscce below.

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) add ItemListener instead of ActionListener, but this ItemListener always fired twice events SELECTED and DESELECTED,

  myComboBox.addItemListener(new ItemListener() {

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

2) your GUI maybe is or isn't created on EventDispashThread, but in this case doesn't matter, you have to delay this method by wraping into invokeLater(), for example

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) better would be implements AutoCompete JComboBox / JTextField for Currency Pairs

4) maybe not important but CcyPairs have got four sides by default

  • Buy BaseCcy

  • Sell BaseCcy

  • Buy VariableCcy

  • Sell VariableCcy

The suggestions so far are good. But sometimes, when things are really convoluted on how Components get constructed, a more direct fix is needed:

  1. subclass the JComboBox (or whatever Swing class is firing the events, JList, etc...)
  2. add a field, private boolean fireEvents = false; Consider making it volatile.
  3. override the relevant fireXXX() methods to check the status of fireEvents
  4. only set fireEvents = true after all construction and initialization is complete
  5. if a "major overhaul" is later called for, such as on loading a new file, new settings, you can set fireEvents back to false while rebuilding everything.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!