如何使用具有null值的JComboBox并使用泛型类型?

时间:2015-02-24 10:18:04

标签: java generics null jcombobox classcastexception

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

当我在抛出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)

1 个答案:

答案 0 :(得分: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;

    }

}