如何修复 NullPointerException 并将数据放入 NatTable
How do I fix NullPointerException and putting data into NatTable
当我尝试使用这段代码时:
students.add(new Student("John","1", 3));
students.add(new Student("Chris","2", 2));
NatTable table = createTable(shell, students);
table.refresh();
出现 NullPointerException,可能是因为 Student class 中的 getter 有问题,或者生成 table。出现此问题时的消息之一也是 ReflectiveColumnPropertyAccessor.getDataValue。我还需要修复 NatTable 中的 ColumnGroup 以正确显示许多考试。
它给了我(我代码中的第 48 行是 Student Constructor):
WARNING: java.lang.NullPointerException
java.lang.RuntimeException: java.lang.NullPointerException
at net.sourceforge.nattable.data.ReflectiveColumnPropertyAccessor.getDataValue(ReflectiveColumnPropertyAccessor.java:48)
at net.sourceforge.nattable.data.ListDataProvider.getDataValue(ListDataProvider.java:36)
at net.sourceforge.nattable.layer.DataLayer.getDataValueByPosition(DataLayer.java:289)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.CompositeLayer.getDataValueByPosition(CompositeLayer.java:547)
at net.sourceforge.nattable.layer.cell.LayerCell.getDataValue(LayerCell.java:166)
at net.sourceforge.nattable.layer.cell.CellDisplayConversionUtils.convertDataType(CellDisplayConversionUtils.java:10)
at net.sourceforge.nattable.painter.cell.AbstractTextPainter.convertDataType(AbstractTextPainter.java:104)
at net.sourceforge.nattable.painter.cell.TextPainter.paintCell(TextPainter.java:96)
at net.sourceforge.nattable.painter.cell.CellPainterWrapper.paintCell(CellPainterWrapper.java:51)
at net.sourceforge.nattable.painter.cell.decorator.LineBorderDecorator.paintCell(LineBorderDecorator.java:64)
at net.sourceforge.nattable.painter.layer.CellLayerPainter.paintCell(CellLayerPainter.java:60)
at net.sourceforge.nattable.selection.SelectionLayerPainter.paintCell(SelectionLayerPainter.java:143)
at net.sourceforge.nattable.painter.layer.CellLayerPainter.paintLayer(CellLayerPainter.java:32)
at net.sourceforge.nattable.painter.layer.GridLineCellLayerPainter.paintLayer(GridLineCellLayerPainter.java:31)
at net.sourceforge.nattable.selection.SelectionLayerPainter.paintLayer(SelectionLayerPainter.java:34)
at net.sourceforge.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:898)
at net.sourceforge.nattable.painter.layer.NatLayerPainter.paintLayer(NatLayerPainter.java:26)
at net.sourceforge.nattable.NatTable.paintNatTable(NatTable.java:313)
at net.sourceforge.nattable.NatTable.paintControl(NatTable.java:309)
at org.eclipse.swt.widgets.TypedListener.handleEvent(Unknown Source)
at org.eclipse.swt.widgets.EventTable.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Display.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Control.gtk_draw(Unknown Source)
at org.eclipse.swt.widgets.Composite.gtk_draw(Unknown Source)
at org.eclipse.swt.widgets.Canvas.gtk_draw(Unknown Source)
at org.eclipse.swt.widgets.Widget.windowProc(Unknown Source)
at org.eclipse.swt.widgets.Control.windowProc(Unknown Source)
at org.eclipse.swt.widgets.Display.windowProc(Unknown Source)
at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(Unknown Source)
at org.eclipse.swt.widgets.Display.eventProc(Unknown Source)
at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(Unknown Source)
at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source)
at student.StudentMain.main(StudentMain.java:585)
我最初的 class 考试和学生。
public static class Student {
private String name;
private String groupNumber;
private Exam[] exams;
public Student() { }
public Student(String name, String groupNumber, int numbOfExams) {
this.name = name;
this.groupNumber = groupNumber;
this.exams = new Exam[numbOfExams];
for(int i=0;i<numbOfExams;i++) {
exams[i]= new Exam();
this.exams[i].setName("");
this.exams[i].setMark(0);
}
}
public String getName() {
return name;
}
public String getGroupNumber() {
return groupNumber;
}
public void setName(String name) {
this.name = name;
}
public void setGroupNumber(String groupNumber) {
this.groupNumber = groupNumber;
}
public void setExam(Exam[] exams) {
this.exams = exams;
}
public Exam[] getExam() {
return exams;
}
}
public static class Exam {
private String name;
private int mark;
public Exam() { }
public Exam(String name, int mark) {
this.name = name;
this.mark = mark;
}
public String getName() {
return name;
}
public int getMark() {
return mark;
}
public void setName(String name) {
this.name = name;
}
public void setMark(int mark) {
this.mark = mark;
}
}
我对NatTable的实现
public static NatTable createTable(final Shell shell, ArrayList<Student> students) {
final ColumnGroupModel columnGroupModel = new ColumnGroupModel();
ColumnHeaderLayer columnHeaderLayer;
String[] propertyNames = { "name", "groupNumber", "examName", "examMark" };
Map<String, String> propertyToLabelMap = new HashMap<String, String>();
propertyToLabelMap.put("name", "Full Name");
propertyToLabelMap.put("groupNumber", "Group");
propertyToLabelMap.put("examName", "Name");
propertyToLabelMap.put("examMark", "Mark");
DefaultBodyDataProvider<Student> bodyDataProvider = new DefaultBodyDataProvider<Student>(students, propertyNames);
ColumnGroupBodyLayerStack bodyLayer = new ColumnGroupBodyLayerStack(new DataLayer(bodyDataProvider), columnGroupModel);
DefaultColumnHeaderDataProvider defaultColumnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
DefaultColumnHeaderDataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(defaultColumnHeaderDataProvider);
columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(columnHeaderLayer, bodyLayer.getSelectionLayer(), columnGroupModel);
columnGroupHeaderLayer.addColumnsIndexesToGroup("Exams", 2, 3);
columnGroupHeaderLayer.setGroupUnbreakable(2);
final DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);
DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
final DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(defaultColumnHeaderDataProvider, rowHeaderDataProvider);
DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, columnGroupHeaderLayer);
GridLayer gridLayer = new GridLayer(
bodyLayer,
columnGroupHeaderLayer,
rowHeaderLayer,
cornerLayer);
NatTable table = new NatTable(shell, gridLayer, true);
return table;
}
你的问题是你有嵌套的对象,你想通过反射来访问它们。那是行不通的!
如果您的 Student
只参加一次考试,您需要将 propertyNames 更改为:
String[] propertyNames = { "name", "groupNumber", "exam.name", "exam.mark" };
以及数据提供者的定义为:
IDataProvider bodyDataProvider =
new ListDataProvider<>(
students,
new ExtendedReflectiveColumnPropertyAccessor<Student>(propertyNames));
但是您的 Student
class 有一个 Exam
对象数组。你想如何在 table 中可视化这样的树结构? NatTable 能够做到这一点,但是你需要更多的东西,比如 TreeLayer
等。而这反过来不适用于你的数据结构。
我建议先想想你想可视化什么,然后检查哪个控件适合你的需要(是 table 还是树?),然后检查一些确实存在的教程,喜欢 NatTable Getting Started Tutorial or the JFace Table tutorial or the JFace Tree tutorial
当我尝试使用这段代码时:
students.add(new Student("John","1", 3));
students.add(new Student("Chris","2", 2));
NatTable table = createTable(shell, students);
table.refresh();
出现 NullPointerException,可能是因为 Student class 中的 getter 有问题,或者生成 table。出现此问题时的消息之一也是 ReflectiveColumnPropertyAccessor.getDataValue。我还需要修复 NatTable 中的 ColumnGroup 以正确显示许多考试。
它给了我(我代码中的第 48 行是 Student Constructor):
WARNING: java.lang.NullPointerException
java.lang.RuntimeException: java.lang.NullPointerException
at net.sourceforge.nattable.data.ReflectiveColumnPropertyAccessor.getDataValue(ReflectiveColumnPropertyAccessor.java:48)
at net.sourceforge.nattable.data.ListDataProvider.getDataValue(ListDataProvider.java:36)
at net.sourceforge.nattable.layer.DataLayer.getDataValueByPosition(DataLayer.java:289)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.AbstractLayerTransform.getDataValueByPosition(AbstractLayerTransform.java:319)
at net.sourceforge.nattable.layer.CompositeLayer.getDataValueByPosition(CompositeLayer.java:547)
at net.sourceforge.nattable.layer.cell.LayerCell.getDataValue(LayerCell.java:166)
at net.sourceforge.nattable.layer.cell.CellDisplayConversionUtils.convertDataType(CellDisplayConversionUtils.java:10)
at net.sourceforge.nattable.painter.cell.AbstractTextPainter.convertDataType(AbstractTextPainter.java:104)
at net.sourceforge.nattable.painter.cell.TextPainter.paintCell(TextPainter.java:96)
at net.sourceforge.nattable.painter.cell.CellPainterWrapper.paintCell(CellPainterWrapper.java:51)
at net.sourceforge.nattable.painter.cell.decorator.LineBorderDecorator.paintCell(LineBorderDecorator.java:64)
at net.sourceforge.nattable.painter.layer.CellLayerPainter.paintCell(CellLayerPainter.java:60)
at net.sourceforge.nattable.selection.SelectionLayerPainter.paintCell(SelectionLayerPainter.java:143)
at net.sourceforge.nattable.painter.layer.CellLayerPainter.paintLayer(CellLayerPainter.java:32)
at net.sourceforge.nattable.painter.layer.GridLineCellLayerPainter.paintLayer(GridLineCellLayerPainter.java:31)
at net.sourceforge.nattable.selection.SelectionLayerPainter.paintLayer(SelectionLayerPainter.java:34)
at net.sourceforge.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:898)
at net.sourceforge.nattable.painter.layer.NatLayerPainter.paintLayer(NatLayerPainter.java:26)
at net.sourceforge.nattable.NatTable.paintNatTable(NatTable.java:313)
at net.sourceforge.nattable.NatTable.paintControl(NatTable.java:309)
at org.eclipse.swt.widgets.TypedListener.handleEvent(Unknown Source)
at org.eclipse.swt.widgets.EventTable.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Display.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Widget.sendEvent(Unknown Source)
at org.eclipse.swt.widgets.Control.gtk_draw(Unknown Source)
at org.eclipse.swt.widgets.Composite.gtk_draw(Unknown Source)
at org.eclipse.swt.widgets.Canvas.gtk_draw(Unknown Source)
at org.eclipse.swt.widgets.Widget.windowProc(Unknown Source)
at org.eclipse.swt.widgets.Control.windowProc(Unknown Source)
at org.eclipse.swt.widgets.Display.windowProc(Unknown Source)
at org.eclipse.swt.internal.gtk.OS._gtk_main_do_event(Native Method)
at org.eclipse.swt.internal.gtk.OS.gtk_main_do_event(Unknown Source)
at org.eclipse.swt.widgets.Display.eventProc(Unknown Source)
at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native Method)
at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(Unknown Source)
at org.eclipse.swt.widgets.Display.readAndDispatch(Unknown Source)
at student.StudentMain.main(StudentMain.java:585)
我最初的 class 考试和学生。
public static class Student {
private String name;
private String groupNumber;
private Exam[] exams;
public Student() { }
public Student(String name, String groupNumber, int numbOfExams) {
this.name = name;
this.groupNumber = groupNumber;
this.exams = new Exam[numbOfExams];
for(int i=0;i<numbOfExams;i++) {
exams[i]= new Exam();
this.exams[i].setName("");
this.exams[i].setMark(0);
}
}
public String getName() {
return name;
}
public String getGroupNumber() {
return groupNumber;
}
public void setName(String name) {
this.name = name;
}
public void setGroupNumber(String groupNumber) {
this.groupNumber = groupNumber;
}
public void setExam(Exam[] exams) {
this.exams = exams;
}
public Exam[] getExam() {
return exams;
}
}
public static class Exam {
private String name;
private int mark;
public Exam() { }
public Exam(String name, int mark) {
this.name = name;
this.mark = mark;
}
public String getName() {
return name;
}
public int getMark() {
return mark;
}
public void setName(String name) {
this.name = name;
}
public void setMark(int mark) {
this.mark = mark;
}
}
我对NatTable的实现
public static NatTable createTable(final Shell shell, ArrayList<Student> students) {
final ColumnGroupModel columnGroupModel = new ColumnGroupModel();
ColumnHeaderLayer columnHeaderLayer;
String[] propertyNames = { "name", "groupNumber", "examName", "examMark" };
Map<String, String> propertyToLabelMap = new HashMap<String, String>();
propertyToLabelMap.put("name", "Full Name");
propertyToLabelMap.put("groupNumber", "Group");
propertyToLabelMap.put("examName", "Name");
propertyToLabelMap.put("examMark", "Mark");
DefaultBodyDataProvider<Student> bodyDataProvider = new DefaultBodyDataProvider<Student>(students, propertyNames);
ColumnGroupBodyLayerStack bodyLayer = new ColumnGroupBodyLayerStack(new DataLayer(bodyDataProvider), columnGroupModel);
DefaultColumnHeaderDataProvider defaultColumnHeaderDataProvider = new DefaultColumnHeaderDataProvider(propertyNames, propertyToLabelMap);
DefaultColumnHeaderDataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(defaultColumnHeaderDataProvider);
columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
ColumnGroupHeaderLayer columnGroupHeaderLayer = new ColumnGroupHeaderLayer(columnHeaderLayer, bodyLayer.getSelectionLayer(), columnGroupModel);
columnGroupHeaderLayer.addColumnsIndexesToGroup("Exams", 2, 3);
columnGroupHeaderLayer.setGroupUnbreakable(2);
final DefaultRowHeaderDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);
DefaultRowHeaderDataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, bodyLayer, bodyLayer.getSelectionLayer());
final DefaultCornerDataProvider cornerDataProvider = new DefaultCornerDataProvider(defaultColumnHeaderDataProvider, rowHeaderDataProvider);
DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, columnGroupHeaderLayer);
GridLayer gridLayer = new GridLayer(
bodyLayer,
columnGroupHeaderLayer,
rowHeaderLayer,
cornerLayer);
NatTable table = new NatTable(shell, gridLayer, true);
return table;
}
你的问题是你有嵌套的对象,你想通过反射来访问它们。那是行不通的!
如果您的 Student
只参加一次考试,您需要将 propertyNames 更改为:
String[] propertyNames = { "name", "groupNumber", "exam.name", "exam.mark" };
以及数据提供者的定义为:
IDataProvider bodyDataProvider =
new ListDataProvider<>(
students,
new ExtendedReflectiveColumnPropertyAccessor<Student>(propertyNames));
但是您的 Student
class 有一个 Exam
对象数组。你想如何在 table 中可视化这样的树结构? NatTable 能够做到这一点,但是你需要更多的东西,比如 TreeLayer
等。而这反过来不适用于你的数据结构。
我建议先想想你想可视化什么,然后检查哪个控件适合你的需要(是 table 还是树?),然后检查一些确实存在的教程,喜欢 NatTable Getting Started Tutorial or the JFace Table tutorial or the JFace Tree tutorial