我创建了一个单元工厂包装器,以启用JavaFX表单元的自定义配置。请参阅下面的代码。
import React, {Component} from 'react';
import {render} from 'react-dom';
import {Router, Route, browserHistory, IndexRoute} from 'react-router';
//Import custom components
import About from '../components/about.js';
import Contact from '../components/contact.js';
import Sidebar from '../components/sidebar.js';
import Imagelist from '../components/image-list.js';
render(
<Router history={browserHistory}>
<Route path="/" component={Sidebar}>
<IndexRoute component={Imagelist}/>
<Route path="/about" component={About}/>
<Route path="/contact" component={Contact}/>
</Route>
</Router>,
document.getElementById('content')
);
这个cellfactory包装器通常可以浏览我的所有tableview。但是,只要我在系统中执行其他功能,例如添加新记录,编辑记录等,就会抛出以下错误。
package idmas.controller.modules.tableview;
import idmas.model.Cml;
import idmas.model.CmlDAO;
import idmas.model.Damageloop;
import idmas.model.modules.general.dateMethods;
import java.util.Date;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;
/**
* Generic cell factory that can be used to override specific properties of cells, such as formatting (text size, color etc.) and even values.
* @author Joshua Adams
* @param <S> = Data type of table view to be modified. E.g. Damageloop, Equipment, CML, Inspection etc.
* @param <T> = Data type of specific cell being overridden. E.g. Date, Integer, Double etc.
*/
public class CellFactoryCustom<S, T> implements Callback<TableColumn<S, T>, TableCell<S, T>> {
//Represents the name of the column for the specific tableview, i.e. Last Internal Inspection Date etc.
String colname;
//Constructors for class wide objects
CmlDAO cmldao = new CmlDAO();
/**
* Class constructor requires a column name to be passed so the specific formatting for that column's cells can be applied.
* @param colname = Name of column to apply formatting to.
*/
public CellFactoryCustom (String colname) {
this.colname = colname;
}
/**
* Main method to override the properties of the cells for a table column.
* @param arg
* @return
*/
@Override
public TableCell<S, T> call(TableColumn<S, T> arg) {
TableCell<S, T> cell = new TableCell<S, T>() {
@Override
protected void updateItem(T item, boolean empty) {
//super allows reffering to methods in superclass
super.updateItem(item, empty);
//recommended syntax for overridding the updateItem method - Refer to update item javadoc.
if (empty || item == null) {
setText(null);
setGraphic(null);
getStyleClass().removeAll("highlightCellBlack");
getStyleClass().add(getTableRow().getStyleClass().toString());
} else {
setConditionalFormatting(this,item);
}
}
};
return cell;
}
/**
* Specific formatting rules which are applied to a columns cells based on its column name.
* @param cell
* @param item
*/
public void setConditionalFormatting (TableCell<S,T> cell, T item) {
//Constructors for reference classes
dateMethods datemethods = new dateMethods();
Date currentdateplus60 = new Date();
Date date;
Damageloop damageloop;
Cml cml;
ComboBox combobox;
//Current styles need to be removed to ensure all specific styles for each cell are applied correctly
cell.getStyleClass().removeAll("highlightCellBlack");
//Switch statement selected over if statement to improve performance of code and readibility
switch (colname) {
case "colNextExternalInspectionDate":
damageloop = (Damageloop) cell.getTableRow().getItem();
cell.setText(datemethods.getDateToString((Date) item,"dd/MM/yyyy"));
currentdateplus60 = datemethods.getDatePlusDays(currentdateplus60, 60);
date = (Date) item;
if(date.before(currentdateplus60) && damageloop.getErrorcode() != 2 & damageloop.getErrorcode() != 3) {
cell.getStyleClass().add("highlightCellBlack");
} else {
cell.getStyleClass().add(cell.getTableRow().getStyleClass().toString());
}
break;
case "colNextInternalInspectionDate":
damageloop = (Damageloop) cell.getTableRow().getItem();
cell.setText(datemethods.getDateToString((Date) item,"dd/MM/yyyy"));
currentdateplus60 = datemethods.getDatePlusDays(currentdateplus60, 60);
date = (Date) item;
if(date.before(currentdateplus60) && damageloop.getErrorcode() != 1 && damageloop.getErrorcode() != 3) {
cell.getStyleClass().add("highlightCellBlack");
} else {
cell.getStyleClass().add(cell.getTableRow().getStyleClass().toString());
}
break;
case "colCmlStatus":
cml = (Cml) cell.getTableRow().getItem();
String[] fieldsArray = new String[]{"C = Continue to Monitor", "S = Scoped", "X = Redundant"};
String[] disabledFieldsArray = new String[]{"S = Scoped"};
String SQLString = "UPDATE IDMAS.CML SET CMLSTATUS = '<NEW_STATUS>' WHERE EQUIPMENT_ID = '" + cml.getEquipmentId() + "' AND CML_NO = " + cml.getCmlNo();
String replacestring = "<NEW_STATUS>";
String defaultvalue = item.toString();
ComboBoxCustom comboboxcustom = new ComboBoxCustom (fieldsArray, disabledFieldsArray, SQLString, replacestring, defaultvalue);
comboboxcustom.setPrefWidth(10);
cell.setGraphic(comboboxcustom);
break;
case "colCmlStatusRemediation":
ObservableList<String> options = FXCollections.observableArrayList(
"A = Approved for Remediation",
"C = Continue to Monitor",
"F = Fit for Service",
"R = Recommend Remediation"
);
cml = (Cml) cell.getTableRow().getItem();
combobox = new ComboBox(options);
combobox.setValue(item.toString());
combobox.setPrefWidth(10);
combobox.valueProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue ov, String oldvalue, String newvalue) {
cml.setCmlstatusremediation(newvalue.charAt(0));
cmldao.updateCml(cml);
//Platform runlater required to update the combox with the new value
Platform.runLater(() -> {
combobox.setValue(String.valueOf(newvalue.charAt(0)));
});
}
});
cell.setGraphic(combobox);
break;
case "colTemporaryrepairinstalled":
cml = (Cml) cell.getTableRow().getItem();
CheckBox checkbox = new CheckBox();
checkbox.setSelected(Boolean.valueOf(item.toString()));
checkbox.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
cml.setTemporaryrepairinstalled(newValue);
cmldao.updateCml(cml);
checkbox.setSelected(newValue);
}
});
cell.setGraphic(checkbox);
break;
default:
break;
}
}
}
我似乎无法弄清楚为什么这个包装器认为我的CML类中有空值。任何人都有任何关于为什么抛出Null Pointer异常的想法?
答案 0 :(得分:3)
在第一次调用TableCell
方法时,无法保证TableRow
已与TableRow
关联,或updateItem
已填充。{ / p>
在您的情况下,getTableRow()
可能会返回null
(这意味着cml = (Cml) cell.getTableRow().getItem();
是抛出异常的行,而不是String SQLString = "UPDATE IDMAS.CML SET CMLSTATUS = '<NEW_STATUS>' WHERE EQUIPMENT_ID = '" + cml.getEquipmentId() + "' AND CML_NO = " + cml.getCmlNo();
);至少在我尝试重现错误时发生了这种情况。
但是如果
String SQLString = "UPDATE IDMAS.CML SET CMLSTATUS = '<NEW_STATUS>' WHERE EQUIPMENT_ID = '" + cml.getEquipmentId() + "' AND CML_NO = " + cml.getCmlNo();
确实是导致错误的行,那么导致这样的堆栈跟踪的唯一方法就是cml
是null
。
解决这个问题的一种方法是根据索引从表中获取项目:
cml = (Cml) cell.getTableView().getItems().get(getIndex());