Java 为什么JComboBox在构建时需要项-1?

Java 为什么JComboBox在构建时需要项-1?,java,swing,custom-controls,jcombobox,Java,Swing,Custom Controls,Jcombobox,我试图理解为什么以下代码不起作用: JComboBox status = new javax.swing.JComboBox(); status.setModel(new DefaultComboBoxModel() { @Override public void addElement(Object anObject) { statusList.add((Requireme

我试图理解为什么以下代码不起作用:

           JComboBox status = new javax.swing.JComboBox();
           status.setModel(new DefaultComboBoxModel() {
            @Override
            public void addElement(Object anObject) {
                statusList.add((RequirementStatus) anObject);
                super.addElement(anObject);
            }

            @Override
            public int getSize() {
                return statusList.size();
            }

            @Override
            public Object getElementAt(int index) {
                return index >= 0 && index < statusList.size()
                        ? statusList.get(index) : null;
            }
        });
        status.setRenderer(new ListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList list,
                    Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {

                return index >= 0 ? new JLabel(
                        ((RequirementStatus) ((ComboBoxModel) status.getModel())
                        .getElementAt(index)).getStatus())
                        : new JLabel("");
            }
        });
我不得不将该条件添加到代码中,因为出于某种原因,在构建GUI时,代码请求在位置-1呈现元素。如果我没有返回带有文本的标签,组合框就不会显示

编辑:

如果此解决方案不存在,则会出现以下错误:

java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.get(ArrayList.java:324)
    at net.sourceforge.javydreamercsw.client.ui.nodes.actions.EditRequirementDialog$5.getElementAt(EditRequirementDialog.java:119)
    at net.sourceforge.javydreamercsw.client.ui.nodes.actions.EditRequirementDialog$6.getListCellRendererComponent(EditRequirementDialog.java:127)
    at javax.swing.plaf.basic.BasicComboBoxUI.getDisplaySize(BasicComboBoxUI.java:1334)
    at javax.swing.plaf.basic.BasicComboBoxUI.getMinimumSize(BasicComboBoxUI.java:903)
    at javax.swing.plaf.basic.BasicComboBoxUI.getPreferredSize(BasicComboBoxUI.java:892)
    at javax.swing.JComponent.getPreferredSize(JComponent.java:1642)
    at javax.swing.GroupLayout$ComponentSpring.calculateNonlinkedPreferredSize(GroupLayout.java:2944)
    at javax.swing.GroupLayout$ComponentSpring.calculatePreferredSize(GroupLayout.java:2905)
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1325)
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1604)
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1593)
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1568)
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1325)
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1604)
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1593)
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1568)
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1325)
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1604)
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1593)
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1568)
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1325)
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1604)
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1590)
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1568)
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1325)
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1604)
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1588)
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1568)
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1325)
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1604)
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1588)
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1568)
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1325)
    at javax.swing.GroupLayout$SequentialGroup.setValidSize(GroupLayout.java:1972)
    at javax.swing.GroupLayout$Group.setSize(GroupLayout.java:1553)
    at javax.swing.GroupLayout.calculateAutopadding(GroupLayout.java:1058)
    at javax.swing.GroupLayout.layoutContainer(GroupLayout.java:897)
    at java.awt.Container.layout(Container.java:1419)
    at java.awt.Container.doLayout(Container.java:1408)
    at java.awt.Container.validateTree(Container.java:1505)
    at java.awt.Container.validateTree(Container.java:1511)
    at java.awt.Container.validateTree(Container.java:1511)
    at java.awt.Container.validateTree(Container.java:1511)
    at java.awt.Container.validate(Container.java:1478)
    at java.awt.Dialog.conditionalShow(Dialog.java:890)
    at java.awt.Dialog.show(Dialog.java:1036)
    at java.awt.Component.show(Component.java:1591)
    at java.awt.Component.setVisible(Component.java:1543)
    at java.awt.Window.setVisible(Window.java:843)
    at java.awt.Dialog.setVisible(Dialog.java:987)
    at net.sourceforge.javydreamercsw.client.ui.nodes.actions.EditRequirementAction$1.run(EditRequirementAction.java:33)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:666)
    at java.awt.EventQueue.access$400(EventQueue.java:81)
    at java.awt.EventQueue$2.run(EventQueue.java:627)
    at java.awt.EventQueue$2.run(EventQueue.java:625)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:636)
    at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
[catch] at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
我知道这应该是一件容易的事情,就像插一面旗子一样,但我找不到它

有什么想法吗

解决方案: 删除模型替代并更改渲染器代码,如下所示:

status.setRenderer(new ListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList list,
                    Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                return index >= 0 ? new JLabel(
                        ((RequirementStatus) value).getStatus())
                        : new JLabel(((RequirementStatus) list.getSelectedValue()).getStatus());
            }
        });
从JComboBox#setRenderer javadoc:

要显示所选项目,将调用arender.getListCellRenderComponent,传递列表对象和索引-1


为了更快地获得更好的帮助,请发布一个。您知道
((ComboBoxModel)status.getModel()).getElementAt(index))
与提供的参数
值严格等效吗?无论如何,如果第一次显示时,当前选定的对象是
null
,并且
null
不是模型的一部分,则UI除了提供-1作为索引外别无选择为什么要覆盖模型?我看不出有任何理由这样做。如果要在模型中存储自定义对象,只需提供一个自定义渲染器来显示该对象的数据。@Guillaume Polet:谢谢您提供的值指针。修正了。@camickr:也修正了。这是由于NetBeans默认代码生成将模型设置为字符串。我删除了它,现在可以在不覆盖模型的情况下工作。这似乎可以解释主要问题。删除模型覆盖并更改渲染器就成功了。有关已编辑的代码,请参见问题。请注意,该值已经是选定的值,因此无需从列表中再次获取该值。渲染器也不会绘制选定/焦点状态。最好扩展DefaultListCellRenderer并将value.getStatus()传递给super.getListCellRenderComponent()
status.setRenderer(new ListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList list,
                    Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                return index >= 0 ? new JLabel(
                        ((RequirementStatus) value).getStatus())
                        : new JLabel(((RequirementStatus) list.getSelectedValue()).getStatus());
            }
        });