Switching FXML files in BorderPane center part in JavaFX

47 Views Asked by At

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.

0

There are 0 best solutions below