【问题标题】:The Stubborn JComboBox顽固的 JComboBox
【发布时间】:2012-01-04 16:19:31
【问题描述】:

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

【问题讨论】:

  • 在创建 JComboBox 后尝试加载 String[]?
  • 拥有异常的堆栈跟踪会有所帮助。如何将 ActionListener 添加到尚未创建的组合框?
  • 你无法避免选择一个值,但即便如此,很明显你的问题出在其他地方。 actionPerformed 处理程序究竟在什么上抛出异常?您可能应该稍后在正确初始化完成后分配它,或者检查它内部的状态。
  • 我从来没有遇到过这个问题。发布您的 SSCCE 来证明问题。
  • 窗口构建器不应该改变任何东西。您没有理由不能手动构建 GUI。事实上,这是我推荐的方法,因为您学习的是 Swing 而不是 GUI。您所要做的就是阅读 JComboBox API 并点击 How to Use Combo Boxes 上的 Swing 教程链接以获取工作示例。

标签: java swing jcombobox


【解决方案1】:

您的(不完整的)示例调用

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

【讨论】:

  • 谢谢。其他答案在一定程度上解决了问题,但仍然存在一些问题,但是这个答案完全解决了。我认为缺少用于构建框架的 invokeLater 函数(即:从 EDT 开始)是主要问题。
  • 感谢您的关注;我总是对揭露 EDT 问题的新方法很感兴趣。
  • @Cemre,你读过 API 和教程吗???教程中的示例正确使用了 EDT,这就是为什么我在几个小时前向您指出了教程。
  • @camickr 您的链接由于某种原因无法正常工作,所以我当时无法检查它,对此感到抱歉。我现在将谷歌并研究它。我对摇摆有点陌生,所以我不知道 EDT 的重要性。感谢您的帮助。
  • @Cemre,我没有给你链接。我希望您能够阅读 API 并自己单击链接。如果您是 Swing 新手,那么更有理由按照建议实际阅读教程,而不是希望有人为您编写代码。
【解决方案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

【讨论】:

  • 非常感谢您的详细回答。对此,我真的非常感激。虽然,您的第二个建议解决了组合框错误,但我仍然遇到空指针异常。
  • @kleopatra 新年快乐
【解决方案3】:

到目前为止的建议都很好。但有时,当组件的构建方式非常复杂时,需要更直接的解决方法:

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

【讨论】:

  • -1 当事情真的很复杂时这主要是因为应用程序代码做错了什么。因此,第一步是挖掘并理解具体上下文中到底出了什么问题,然后修复那个
猜你喜欢
  • 2013-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多