【问题标题】:can't remove first element from jcombobox无法从 jcombobox 中删除第一个元素
【发布时间】:2011-08-24 12:27:28
【问题描述】:

我无法从 jcombobox 中删除第一个元素。我的代码如下,

JComboBox cBox= cBox= new JComboBox();
...    
while (cBox.getItemCount() > 0)
  cBox.removeItemAt(0);

对于测试运行,我在 cBox 中有 3 个项目。当它到达 removeItemAt(0) 时,调试变得混乱,进入了一些绝对不相关的文件访问代码。这样做两次然后得到以下异常。我尝试了直接得到相同异常的 removeAllItems() 。但是, removeItem(1) 可以正常工作,直到只剩下 1 个元素。该异常不会使应用程序崩溃,之后我在组合框中看不到任何项目,因此它工作了一点。我到底做错了什么。

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at util.Gui$4.actionPerformed(Gui.java:111)
at javax.swing.JComboBox.fireActionEvent(Unknown Source)
at javax.swing.JComboBox.contentsChanged(Unknown Source)
at javax.swing.AbstractListModel.fireContentsChanged(Unknown Source)
at javax.swing.DefaultComboBoxModel.setSelectedItem(Unknown Source)
at javax.swing.DefaultComboBoxModel.removeElementAt(Unknown Source)
at javax.swing.JComboBox.removeItemAt(Unknown Source)
at util.Gui.prepareSubLists(Gui.java:164)
at util.Gui$3.actionPerformed(Gui.java:97)
at javax.swing.JComboBox.fireActionEvent(Unknown Source)
at javax.swing.JComboBox.setSelectedItem(Unknown Source)
at javax.swing.JComboBox.setSelectedIndex(Unknown Source)
at javax.swing.plaf.basic.BasicComboPopup$Handler.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at javax.swing.plaf.basic.BasicComboPopup$1.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

【问题讨论】:

  • 如果你把你的实际代码放在这里会很有用。这可能是 mre 所说的 while 条件,或者是导致某处 NPE 的任何其他问题!
  • 问题出在您未显示的代码中,请参阅堆栈跟踪的第一行:at util.Gui$4.actionPerformed(Gui.java:111)
  • 我必须添加一个空白项目,然后删除其余的。似乎无法从组合框项目中删除所有项目。
  • 再次:最有可能的问题是 not 删除项目(无论它们是什么,默认组合都经过了足够好的测试 - 被 15 岁以上的开发人员军团使用应该保证,我们同意吗?)。取而代之的是 Gui.java 第 111 行有问题。不要添加随机黑客,深入挖掘并理解原因......
  • removeItemAt(0) 也会触发事件 actionPerformed() 并且有时用户将代码放在这里,它指的是不幸在几毫秒前被删除的项目。在@kleopatra 下方查看更详细的分析器

标签: java swing jcombobox


【解决方案1】:

你的条件语句是不是错了?将while替换为if,这样

if(cBox.getItemCount() > 0){
  cBox.removeItemAt(0);
}

这是SSCCE

public final class JComboBoxDemo {
    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                createAndShowGUI();             
            }
        });
    }

    public static void createAndShowGUI(){
        final JFrame frame = new JFrame("JComboBox Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(JComboPane.newInstance());
        frame.setSize(new Dimension(250, 100)); // for demonstration purposes only
        //frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private static final class JComboPane extends JPanel{
        private JComboPane(){
            super();
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            JCenteredComboBox comboBox = JCenteredComboBox.newInstance();
            JCenteredButton button = JCenteredButton.newInstance(comboBox);
            add(comboBox);
            add(button);
        }

        public static final JComboPane newInstance(){
            return new JComboPane();
        }

        private static final class JCenteredComboBox extends JComboBox{
            private JCenteredComboBox(){
                super(new String[]{"Item 1", "Item 2", "Item 3"});
                setAlignmentX(Component.CENTER_ALIGNMENT);
            }

            public static final JCenteredComboBox newInstance(){
                return new JCenteredComboBox();
            }
        }

        private static final class JCenteredButton extends JButton{
            private JCenteredButton(final JComboBox comboBox){
                super("Remove First Item");
                setAlignmentX(Component.CENTER_ALIGNMENT);
                addActionListener(new ActionListener(){
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if(comboBox.getItemCount() > 0){
                            comboBox.removeItemAt(0); // your logic
                        }
                    }
                });
            }

            public static final JCenteredButton newInstance(final JComboBox comboBox){
                return new JCenteredButton(comboBox);
            }
        }
    }
}

当你运行它时,按下JButton 将删除JComboBox 中的第一项。你可以一直按到它为空。

【讨论】:

  • 暂时看不到任何错误 - 逻辑与您的 if 相同,只是重复。我错过了什么?
  • @kleopatra,你是对的。看起来 OP 本质上是在执行“全部删除”。但这仍然意味着逻辑是错误的。问题肯定出在其他地方。如果 OP 不更新我们,我将删除此答案。
  • 你的解决方案工作得很好,我在实际代码中做了一些孤立的部分,但这似乎也失败了。该应用程序唯一接受的是当我添加一个空白然后删除其余部分时。我也尝试了 MutableComboBoxModel,但如果要删除所有内容,结果相同。我将全部删除,然后一点一点地添加,看看它在哪里爆炸:)。不过谢谢
  • public void prepareSubLists() throws FileNotFoundException { subCategoryList.clear(); subCategoryList=fileHandler.getSubCategory(kategori.getSelectedItem().toString()); //测试的东西 MutableComboBoxModel mcbm=(MutableComboBoxModel)cBox.getModel(); int initialSize=cBox.getItemCount();整数断路器=0; cBox.addItem("");//必须添加 while(cBox.getItemCount()>0) { Object item = cBox.getItemAt(0); mcbm.removeElement(项目); ++断路器; if(breaker>=initialSize) 中断; } if(subCategoryList!=null) for(int i=0;i
  • 这行得通。抱歉弄得一团糟,但我 8 小时没有回复。
【解决方案2】:

这个异常可能是因为当一个组合项被移除时触发了一个事件,而在这个事件处理方法中你仍然引用组合框项。

例如,当您使用 combo.removeItemAt(0) 或 removeAllItems() 从组合框中删除代码中的某个位置(除了 actionPeformed() 之外)时,仍然会触发/执行事件 actionPerformed。但通常 actionPerformed() 方法包含对用户操作(用户单击组合框上的某处)做出反应的代码。因此,当最后一个项目被删除时,组合框中将不再有任何项目,并且在 actionPerformed() 中对项目或索引的任何引用都会导致异常。

解决方案是将代码从 actionPerformed 移动到例如mouseClicked() 或其他事件处理程序,具体取决于您要执行的操作。

【讨论】:

  • 不,这不会发生在行为良好的代码中 ;-) 为了使其行为良好,只需始终检查您想要做某事的项目是否仍在模型中 - 在 任何方法(包括actionPerformed)
猜你喜欢
  • 2017-08-13
  • 1970-01-01
  • 2017-02-25
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多