顽固的 JComboBox

发布于 2024-12-24 17:27:50 字数 1942 浏览 2 评论 0原文

我有一个 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);
    }
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

疧_╮線 2024-12-31 17:27:50

您的(不完整)示例

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

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);
    }
}
烙印 2024-12-31 17:27:50

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) 可以更好地实现此方法 货币对的自动竞争 JComboBox / JTextField

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

  • 购买 BaseCcy

  • 卖出 BaseCcy

  • 买入VariableCcy

  • 卖出 VariableCcy

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

无风消散 2024-12-31 17:27:50

到目前为止的建议都很好。但有时,当组件的构造方式确实很复杂时,需要更直接的修复:

  1. 子类化 JComboBox(或触发事件的任何 Swing 类,JList 等...)
  2. 添加一个字段,private boolean fireEvents = false;考虑使其变得易失性
  3. 重写相关的 fireXXX() 方法来检查 fireEvents 的状态,
  4. 仅在所有构建和初始化完成后设置 fireEvents = true
  5. 如果稍后需要进行“大修”,例如在加载新文件、新设置时,您可以在重建所有内容时将 fireEvents 设置回 false。

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文