I tried to create a program in JavaFX which enables to show list of books and add new books.
I used a BorderPane as my main view and put a ScrollPane into the CENTEER part of BorderPane.
My ScrollPane contains VBox to which I add the list of another FXML files - separate HBox for each book ('book cards').
I have BookCardController with method setCard:
public class BookCardController implements Initializable {
@FXML
private Label bookAuthor;
@FXML
private HBox bookBox;
@FXML
private ImageView bookImage;
@FXML
private ChoiceBox<String> bookList;
private String[] statuses = {"Want to read", "Currently reading", "Read"};
@FXML
private Label bookTitle;
public void setCard(Book book){
Image image = new Image(getClass().getResourceAsStream(book.getImageSrc()));
bookImage.setImage(image);
bookTitle.setText(book.getTitle());
bookAuthor.setText(book.getAuthor());
bookList.setValue(statuses[book.getBookListId()]);
}
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
bookList.getItems().addAll(statuses);
}
In my MainController class I created setBookListView() method which loads BookCard.fxml for each of the Books objects added to the list:
public class MainController implements Initializable {
@FXML
VBox VBoxBooks = new VBox();
@FXML
BorderPane BorderPaneList;
private List<Book> userBooks;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
setBookListView();
}
public void setBookListView() {
userBooks = new ArrayList<>(addUserBooks());
try {
for (int i = 0; i < userBooks.size(); i++) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/BookCard.fxml"));
HBox bookCard = loader.load();
BookCardController bookCardController = loader.getController();
bookCardController.setCard(userBooks.get(i));
VBoxBooks.getChildren().add(bookCard);
}
} catch (IOException e) {
e.printStackTrace();
}
}
It works great, but there is a problem.
I added a button which enables to add a new book. After clicking it, the center part of BorderPane changes to FXML file which contains a form for adding a new book with two buttons: 'save' and 'cancel'. My goal is to return to the previous view (ScrollPane with VBox containing all books cards) after clicking one of these buttons, but I don't know how to do it correctly.
Here is my function which changes the center part of BorderPane:
public void setCenter(String fxmlPath){
FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlPath));
parent = null;
try {
parent = loader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
BorderPaneList.setCenter(parent);
}
Here is my 'onAction' function for 'add new book' button:
public void switchToForm(ActionEvent event) {
setCenter("/fxml/AddNewBook.fxml");
}
Here are my problematic 'onAction' functions for the two mentioned buttons:
public void save(ActionEvent actionEvent) {
setBookListView();
}
public void cancel(ActionEvent actionEvent) {
setBookListView();
}
My Main.java functions uses FXMLLoader to load my main BorderPane view (with empty scrollpane containing VBox).
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(this.getClass().getResource("/fxml/BorderPaneList.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("Better Reads");
stage.setScene(scene);
stage.show();
}
I tried switching scenes - I created two separate BorderPane fxml files - one with loading of list of book cards using mentioned function - setBookListView(), one with a form to add a new book.
I tried also calling a setBookListView() again in these two 'onAction' methods but it doesn't work.
There was an error which said that my VBoxBooks.getChildren() is a null but after its initialization, the error no longer appears. Currently the program works, list of books appears in a ScrollPane and after clicking 'add new book' button, the form appears but I can't do anything after that, because I don't know how to properly change the view to the previous one.
I don't know how should I correctly change the center part of BorderPane and I would appreciate your help.