I have 3 classes the first one is Library Item this is the super class. The other two classes are Book and Movie. When I want to fill my table view I want to make sure the correct property is called when populating the table view. I know it is easier to just call the director and author the same for ease of use, but I want to get it working for learning purposes. I have left out packages and imports for relevance.
LibraryItem class
public abstract class LibraryItem {
private int itemCode;
private String title;
private boolean availability;
private int memberIdentifier;
private LocalDate dateLent;
protected LibraryItem(int itemCode, String title, boolean availability, int memberIdentifier, LocalDate dateLent) {
this.itemCode = itemCode;
this.title = title;
this.availability = availability;
this.memberIdentifier = memberIdentifier;
this.dateLent = dateLent;
}
public int getItemCode() {
return itemCode;
}
public String getTitle() {
return title;
}
public boolean isAvailability() {
return availability;
}
public void setAvailability(boolean availability) {
this.availability = availability;
}
public int getMemberIdentifier() {
return memberIdentifier;
}
public void setMemberIdentifier(int memberIdentifier) {
this.memberIdentifier = memberIdentifier;
}
public LocalDate getDateLent() {
return dateLent;
}
public void setDateLent(LocalDate dateLent) {
this.dateLent = dateLent;
}
}
Book class
public class Book extends LibraryItem {
private String author;
protected Book(int itemCode, String title, boolean isLent, int memberIdentifier, LocalDate dateLent, String author) {
super(itemCode, title, isLent, memberIdentifier, dateLent);
this.author = author;
}
}
Movie class
public class Movie extends LibraryItem {
private String director;
protected Movie(int itemCode, String title, boolean isLent, int memberIdentifier, LocalDate dateLent, String director) {
super(itemCode, title, isLent, memberIdentifier, dateLent);
this.director = director;
}
}
I was thinking maybe there is some kind of check I can do for each row implemented so the correct value will be given,
This was my attempt:
public class CollectionController implements Initializable {
@FXML
private TableView<LibraryItem> libraryItemsTable;
@FXML
private TableColumn<LibraryItem, String> itemCodeColumn;
@FXML
private TableColumn<LibraryItem, String> availableColumn;
@FXML
private TableColumn<LibraryItem, String> titleColumn;
@FXML
private TableColumn<LibraryItem, String> authorDirectorColumn;
private LibraryService libraryService = new LibraryService();
@Override
public void initialize(URL location, ResourceBundle resources) {
initializeTableView();
}
private void initializeTableView() {
List<LibraryItem> libraryItems = libraryService.getLibraryItems();
itemCodeColumn.setCellValueFactory(new PropertyValueFactory<>("itemCode"));
availableColumn.setCellValueFactory(new PropertyValueFactory<>("availability"));
titleColumn.setCellValueFactory(new PropertyValueFactory<>("title"));
// implement here check for each new row
if (checkIfBook(row))
authorDirectorColumn.setCellValueFactory(new PropertyValueFactory<>("author"));
else
authorDirectorColumn.setCellValueFactory(new PropertyValueFactory<>("director"));
//
libraryItemsTable.getItems().addAll(libraryItems);
}
If you follow the advice here and avoid the use of PropertyValueFactory
, the solution becomes reasonably clear:
titleColumn.setCellValueFactory(data ->
new SimpleStringProperty(data.getValue().getTitle()));
authorDirectorColumn.setCellValueFactory(data -> {
LibraryItem item = data.getValue();
if (item instanceof Book book) {
return new SimpleStringProperty(book.getAuthor());
} else if (item instanceof Movie movie) {
return new SimpleStringProperty(movie.getProducer());
} else {
return null ;
}
});
Here's a complete example (I simplified the model classes for brevity, but retained enough to demonstrate the point):
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
TableView<LibraryItem> table = new TableView<>();
TableColumn<LibraryItem, String> titleColumn = new TableColumn<>("Title");
TableColumn<LibraryItem, String> authorProducerColumn = new TableColumn<>("Author/Producer");
table.getColumns().add(titleColumn);
table.getColumns().add(authorProducerColumn);
titleColumn.setCellValueFactory(data -> new SimpleStringProperty(data.getValue().getTitle()));
authorProducerColumn.setCellValueFactory(data -> {
LibraryItem item = data.getValue();
if (item instanceof Book book) {
return new SimpleStringProperty(book.getAuthor());
} else if (item instanceof Movie movie) {
return new SimpleStringProperty(movie.getProducer());
} else return null ;
});
for (int i = 1 ; i <= 10 ; i++) {
Book book = new Book("Book "+i, "Author "+i);
Movie movie = new Movie("Movie "+i, "Producer "+i);
table.getItems().addAll(book, movie);
}
BorderPane root = new BorderPane(table);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public class LibraryItem {
private String title ;
public LibraryItem(String title) {
this.title = title ;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
public class Movie extends LibraryItem {
private String producer ;
public Movie(String title, String producer) {
super(title);
this.producer = producer ;
}
public String getProducer() {
return producer;
}
public void setProducer(String producer) {
this.producer = producer;
}
}
public class Book extends LibraryItem {
private String author ;
public Book(String title, String author) {
super(title);
this.author = author ;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
public static void main(String[] args) {
launch();
}
}