I'm currently writing a program with JavaFX and FXML. My current problem is that I have an FXMLTableView
, which should display traits of two different object-classes, Stockorder
and Article
, namely the name, id and price of the article and how many of that article are in stock (which is defined in stockorder). I currently have the following Code:
Stockorder:
public class Stockorder {
private SimpleStringProperty deliveryState;
private SimpleStringProperty stockOrderId;
private SimpleStringProperty orderdate;
private SimpleStringProperty deliverydate;
private SimpleStringProperty count;
private SimpleStringProperty itemId;
private SimpleStringProperty itemName;
public Stockorder(String deliveryState, String stockOrderId, String orderdate, String deliverydate, String count, String itemId, String itemName) {
this.deliveryState = new SimpleStringProperty(deliveryState);
this.stockOrderId = new SimpleStringProperty(stockOrderId);
this.orderdate = new SimpleStringProperty(orderdate);
this.deliverydate = new SimpleStringProperty(deliverydate);
this.count = new SimpleStringProperty(count);
this.itemId = new SimpleStringProperty(itemId);
this.itemName = new SimpleStringProperty(itemName);
}
public boolean getDeliveryState() {
return Boolean.valueOf(deliveryState.get());
}
public StringProperty getDeliveryStateProperty() {
return deliveryState;
}
public int getStockOrderId() {
return Integer.parseInt(stockOrderId.get());
}
public StringProperty getStockOrderIdProperty() {
return stockOrderId;
}
public String getOrderdate() {
return orderdate.get();
}
public StringProperty getOrderdateProperty() {
return orderdate;
}
public String getDeliverydate() {
return deliverydate.get();
}
public StringProperty getDeliverydateProperty() {
return deliverydate;
}
public int getCount() {
return Integer.parseInt(count.get());
}
public StringProperty getCountProperty() {
return count;
}
public int getItemId() {
return Integer.parseInt(itemId.get());
}
public StringProperty getItemIdProperty() {
return itemId;
}
public String getItemName() {
return itemName.get();
}
public StringProperty getItemNameProperty() {
return itemName;
}
}
Article:
public class Article {
private final SimpleStringProperty articleNr;
private final SimpleStringProperty name;
private final SimpleStringProperty price;
public Article(String articleNr, String name, String price) {
this.articleNr = new SimpleStringProperty(articleNr);
this.name = new SimpleStringProperty(name);
this.price = new SimpleStringProperty(price);
}
public int getArticleNr() {
return Integer.parseInt(articleNr.get());
}
public String getName() {
return name.get();
}
public double getPrice() {
return Double.parseDouble(price.get());
}
public StringProperty getArticleNrProperty(){
return articleNr;
}
public StringProperty getNameProperty(){
return name;
}
public StringProperty getPriceProperty(){
return price;
}
}
EditArticleOverviewControl (FXMLController)
public class EditArticlesOverviewController implements Initializable {
public EditArticlesOverviewController() {
System.out.println("EditArticleOverviewController started");
}
private ApplicationControl applicationControl;
private EditOrderController editOrderController = new EditOrderController();
private String stockOrderURL = "stockorders";
private HttpClient client = new HttpClient();
@FXML
TableView<Article> tableView;
@FXML
TableColumn<Article, String> articleNrColumn;
@FXML
TableColumn<Article, String> nameColumn;
@FXML
TableColumn<Article, String> priceColumn;
@FXML
TableColumn<Stockorder, String> stockColumn;
@FXML
TableColumn<Stockorder, String> minStockColumn;
@FXML
TableColumn<Stockorder, String> addColumn;
@FXML
Button cancelButton;
@Override
public void initialize(URL url, ResourceBundle rb) {
articleNrColumn.setCellValueFactory(cellData -> cellData.getValue().getArticleNrProperty());
nameColumn.setCellValueFactory(cellData -> cellData.getValue().getNameProperty());
priceColumn.setCellValueFactory(cellData -> cellData.getValue().getPriceProperty());
stockColumn.setCellValueFactory(cellData -> cellData.getValue().getCountProperty());
minStockColumn.setCellValueFactory(cellData -> cellData.getValue().getDeliveryStateProperty());
addColumn.setCellValueFactory(cellData -> cellData.getValue().getCountProperty());
}
public void setApplicationControl(ApplicationControl applicationControl) {
this.applicationControl = applicationControl;
}
public void setEntriesInTableView(ObservableList articlesList) {
tableView.setItems(articlesList);
}
@FXML
public void goBack() {
System.out.println("Kein Artikel bearbeitet");
Stage stage = (Stage) cancelButton.getScene().getWindow();
stage.close();
//EditOrder wieder starten vom selben Order wie vorher!!
try {
applicationControl.openEditOrder(applicationControl.order.getOrderNr());
} catch (Exception ex) {
Logger.getLogger(OrdersOverviewController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Now every time I try to run the program, I get the error:
java.lang.ClassCastException: client.Article cannot be cast to client.Stockorder
at the line where I set the cellValueFactory
for stockOrder
. But I can't understand why, as the column holds Stockorder
and the cellValueFactory
uses methods of the Stockorder
class.
At your code,
TableColumn<Stockorder, String> stockColumn;
It means stockColumn
will try to get items as Stockorder. The S of TableColumn<S, T>
affects S of setCellValueFactory(Callback<TableColumn.CellDataFeatures<S,T>,ObservableValue<T>> value)
and return type S of TableColumn.CellDataFeatures<S,T>::getValue()
.
But actually, items in the TableView
is not instance of Stockorder
, so ClassCastException
is thrown at runtime. All S type of TableView<S>
and TableColumn<S,T>
must be same.
In this case, to show them in a TableView
, there is a need to create a data model class for use it. For example:
class RowData {
private Stockorder stockorder;
private Article article;
public RowData(Arthicle article, Stockorder stockorder) {
this.article = article;
this.stockorder = stockorder;
}
public Stockorder getStockorder(){ return stockorder; }
public Article getArticle(){ return arthicle; }
}