2015-02-24 70 views
1

我使用带泛型(Java 7)的JComboBox,非常有用,因为我不需要一直投射,而且我使用自定义渲染来正确显示对象。如何使用带有空值的JComboBox并使用泛型?

我的问题是当我添加一个空值,因为它抛出一个java.lang.ClassCastException。我的ListCellRenderer是好的,它可以处理null值,但是这个异常发生之前它可以呈现它。

果然不出我所发现的是,javax.swing.plaf.basic.BasicComboBoxUI做到这一点:

if (value == null) { 
     value = " "; 
} else if (value instanceof String && "".equals(value)) { 
     value = " "; 
} 
Component component = renderer.getListCellRendererComponent(listBox, value, -1, false, false); 

所以转换null成空白String因此类转换异常。

我唯一能想到的就是让我的救世主接受对象类型并检查那里的价值等级,如果它是" "假设这就像null(女巫我看不出它是非常正确的) 。

该行引发异常Component component = renderer.getListCellRendererComponent(listBox, value, -1, false, false);,因为value是一个String并且呈现的只接受MyClass对象。

可以做些什么?这是避免这种转换的方法吗?


这里就像是我所使用的代码:

JComboBox plantillaMarcoB = new JComboBox<MyClass>(); 
plantillaMarcoB.setRenderer(new Visualizador); 
DefaultComboBoxModel<MyClass> modeloA = new DefaultComboBoxModel<MyClass>(); 
modeloB.addElement(null); 
modeloB.addElement(new MyClass()); 
this.plantillaMarcoB.setModel(modeloB); 

这是Visualizador类:

package es.phoneixs; 

import java.awt.Component; 

import javax.swing.JComboBox; 
import javax.swing.JLabel; 
import javax.swing.JList; 
import javax.swing.ListCellRenderer; 

import es.phoneixs.MyClass; 


public class Visualizador extends JLabel implements 
     ListCellRenderer<MyClass> { 

    public Visualizador() { 

     setOpaque(true); 
     setVerticalAlignment(CENTER); 

    } 

    @Override 
    public Component getListCellRendererComponent(
      JList<? extends MyClass> list, 
      MyClass value, int index, boolean isSelected, 
      boolean cellHasFocus) { 

     this.setFont(list.getFont()); 

     if (isSelected) { 
      setBackground(list.getSelectionBackground()); 
      setForeground(list.getSelectionForeground()); 
     } else { 
      setBackground(list.getBackground()); 
      setForeground(list.getForeground()); 
     } 

     if (value == null) { 

      this.setText("No usar la plantilla"); 

     } else { 

      this.setText(String.format("%1$s - %2$s - %3$s", value.getDescripcionCas(), value.getCodigo(), value.getTurno())); 

     } 

     return this; 

    } 

} 

这是异常抛出:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.String cannot be cast to es.phoneixs.MyClass 
    at es.phoneixs.Visualizador.getListCellRendererComponent(Visualizador.java:1) 
    at javax.swing.plaf.basic.BasicComboBoxUI.getBaseline(BasicComboBoxUI.java:979) 
    at javax.swing.plaf.metal.MetalComboBoxUI.getBaseline(MetalComboBoxUI.java:149) 
    at javax.swing.JComponent.getBaseline(JComponent.java:2561) 
    at javax.swing.GroupLayout$ComponentSpring.getBaseline(GroupLayout.java:3075) 
    at javax.swing.GroupLayout$BaselineGroup.calculateBaselineAndResizeBehavior(GroupLayout.java:2732) 
    at javax.swing.GroupLayout$BaselineGroup.calculateSize(GroupLayout.java:2708) 
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1602) 
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1346) 
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1638) 
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1627) 
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1602) 
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1346) 
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1638) 
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1622) 
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1602) 
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1346) 
    at javax.swing.GroupLayout$Group.getSpringSize(GroupLayout.java:1638) 
    at javax.swing.GroupLayout$Group.calculateSize(GroupLayout.java:1622) 
    at javax.swing.GroupLayout$Group.calculatePreferredSize(GroupLayout.java:1602) 
    at javax.swing.GroupLayout$Spring.getPreferredSize(GroupLayout.java:1346) 
    at javax.swing.GroupLayout$SequentialGroup.setValidSize(GroupLayout.java:2017) 
    at javax.swing.GroupLayout$Group.setSize(GroupLayout.java:1587) 
    at javax.swing.GroupLayout.calculateAutopadding(GroupLayout.java:1079) 
    at javax.swing.GroupLayout.layoutContainer(GroupLayout.java:920) 
    at java.awt.Container.layout(Container.java:1503) 
    at java.awt.Container.doLayout(Container.java:1492) 
    at java.awt.Container.validateTree(Container.java:1688) 
    at java.awt.Container.validateTree(Container.java:1697) 
    at java.awt.Container.validate(Container.java:1623) 
    at java.awt.CardLayout.show(CardLayout.java:547) 
+0

@kocko什么是“NPE”? – PhoneixS 2015-02-24 10:23:12

+0

这不是一个NPE,它是一个ClassCastException – PhoneixS 2015-02-24 10:25:31

+1

对不起,我仍然昏昏欲睡:) – 2015-02-24 10:25:52

回答

2

我发现它是实施中的一个错误的jvm。你可以在https://bugs.openjdk.java.net/browse/JDK-7195179看到这个报告,不幸的是它似乎对于Java 8是固定的。

我发现的唯一工作就是改变Visualizador以接受字符串。

package es.phoneixs; 

import java.awt.Component; 

import javax.swing.JComboBox; 
import javax.swing.JLabel; 
import javax.swing.JList; 
import javax.swing.ListCellRenderer; 

import es.phoneixs.MyClass; 


public class Visualizador extends JLabel implements 
     ListCellRenderer<Object> { 

    public Visualizador() { 

     setOpaque(true); 
     setVerticalAlignment(CENTER); 

    } 

    @Override 
    public Component getListCellRendererComponent(
      JList<? extends Object> list, 
      Object value, int index, boolean isSelected, 
      boolean cellHasFocus) { 

     this.setFont(list.getFont()); 

     if (isSelected) { 
      setBackground(list.getSelectionBackground()); 
      setForeground(list.getSelectionForeground()); 
     } else { 
      setBackground(list.getBackground()); 
      setForeground(list.getForeground()); 
     } 

     if (value == null || (value instanceof String && value.equals(" "))) { 

      this.setText("No usar la plantilla"); 

     } else if (value instanceof MyClass) { 

      this.setText(String.format("%1$s - %2$s - %3$s", value.getDescripcionCas(), value.getCodigo(), value.getTurno())); 

     } else { 
      this.setText(value.toString()); 
     } 

     return this; 

    } 

} 
+2

是的,我刚刚通过检查源代码得出了相同的结论。他们在不使代码使用类型安全的情况下生成了这个类。 CCE引发到方法调用站点,在那里隐式向你的类发送。在源代码中不可见,因此堆栈跟踪中显示“行1”。 – 2015-02-24 10:57:47