如何使用具有空值的 JComboBox 并使用泛型类型?
How to use a JComboBox with null value and using generic types?
我将 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
转换为白色 space String
,因此 class 强制转换异常。
我唯一能想到的就是让我的 rederer 接受对象类型并在那里检查值的 class 如果它是 " "
假设就像 null
( 我认为它不是很正确)。
此行抛出异常 Component component = renderer.getListCellRendererComponent(listBox, value, -1, false, false);
,因为值是一个字符串,并且呈现的只接受 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);
这是可视化工具 class:
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)
我发现是jvm实现的bug。您可以在 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;
}
}
我将 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
转换为白色 space String
,因此 class 强制转换异常。
我唯一能想到的就是让我的 rederer 接受对象类型并在那里检查值的 class 如果它是 " "
假设就像 null
( 我认为它不是很正确)。
此行抛出异常 Component component = renderer.getListCellRendererComponent(listBox, value, -1, false, false);
,因为值是一个字符串,并且呈现的只接受 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);
这是可视化工具 class:
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)
我发现是jvm实现的bug。您可以在 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;
}
}