2015-02-24 68 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