The Stubborn JComboBox

若如初见. 提交于 2019-12-22 08:56:02

问题


I have a JComboBox shown in the code below. When the program starts its actionPerformed event fires up immediately causing some null pointer exceptions so I want to start with none of the elements selected. However, for some reason it does not work (it always start with displaying "USD/TRY" whatever I do). Anyone has any idea ?

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

UPDATE: Building the combo box like below doesnt change anything either

JComboBox comboBox = new JComboBox(); 

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

Here is the 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);
    }
}

回答1:


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



回答2:


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




回答3:


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.


来源:https://stackoverflow.com/questions/8730116/the-stubborn-jcombobox

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!