0

I'm creating a week view for a simple scheduling application in JavaFX. The view consists of a 8x49 GridPane. The first column shows times and the first row shows the days of the week, similar to the week view on Google calendar and other calendar software. When the user changes the date, I want to clear the grid except for the first column and first row. I borrowed a method from an answer in another SO question. It works perfectly in my day view panel (exactly the same code except is a 2x49 grid instead) but throws a NullPointerException in my week view panel.

I added two System.out.println() statements to see if anything is actually null. As far as I can tell, nothing is. I removed GridPane.getRowIndex(node) == row to see if that might be the issue and the exception no longer happened, leading me to believe this statement is somehow causing the exception.

Here is the offending method, borrowed from Shreyas Dave. I added line numbers for correlation with the stack trace below:

130: private Node getNodeFromGridPane(GridPane gridPane, int col, int row) {
131:     System.out.println("Gridpane: " + gridPane.getChildren().toString());
132:     for (Node node : gridPane.getChildren()) {
133:         System.out.println("Node: " + node.toString());
134:         if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
135:             return node;
136:         }
137:     }
138:     return null;
139: }

Here is the method that calls getNodeFromGridPane:

    private void clearAppointmentsColumn(){
        for(int i = 0; i < 49; i++){
            Node node = getNodeFromGridPane(grid, 1, i+1);
            if(node != null){
                grid.getChildren().remove(node);
            }
        }
    }

Here is the output of the System.out.println() statements and the relevant part of the stack trace:

Gridpane: [Label@4b093381[styleClass=label]'Monday', Label@44994e49[styleClass=label]'Tuesday', Label@6f3b59bb[styleClass=label]'Saturday', Label@61dea913[styleClass=label]'Sunday', Label@2f46425[styleClass=label]'Thursday', Label@37370341[styleClass=label]'Wednesday', HBox@3b64a2ab, HBox@3031ce6e, HBox@2e8b5a86, HBox@7d2748fa, HBox@1f40aa1b, HBox@46404c48, HBox@6b829580, HBox@131fffd9, HBox@5a3e3d63, HBox@2f889183, HBox@5d56c9f0, HBox@5f2d13f2, HBox@37bf973, HBox@145f557e, HBox@6db9d36a, HBox@738a8500, HBox@49655482, HBox@75505497, HBox@5b1abd8b, HBox@557f1cad, HBox@223c3dd1, HBox@4d317b8e, HBox@3b093ec, HBox@1183928c]
Node: Label@4b093381[styleClass=label]'Monday'
Node: Label@44994e49[styleClass=label]'Tuesday'
Node: Label@6f3b59bb[styleClass=label]'Saturday'
Node: Label@61dea913[styleClass=label]'Sunday'
Caused by: java.lang.NullPointerException
    at appointmentcalendar.WeekViewController.getNodeFromGridPane(WeekViewController.java:134)
    at appointmentcalendar.WeekViewController.clearAppointmentsColumn(WeekViewController.java:108)
    at appointmentcalendar.WeekViewController.setDate(WeekViewController.java:74)
    at appointmentcalendar.MainWindowController.refreshWeekView(MainWindowController.java:467)
    at appointmentcalendar.MainWindowController.datePicked(MainWindowController.java:455)
    at appointmentcalendar.AppointmentCalendar.switchToMainWindow(AppointmentCalendar.java:90)
    at appointmentcalendar.LoginFormController.loginClicked(LoginFormController.java:71)
    ... 75 more

Line 134 is the if statement in getNodeFromGridPane.

As I said, this method works perfectly in my DayViewController which is literally the same code (WeekViewController.java and WeekView.fxml are a direct copy and paste duplicates, the only difference thus far is the number of columns in the GridPane). When run on the WeekViewController, the method processes exactly 4 nodes before throwing the exception. They are the same 4 nodes every time. I tried removing the 5th node from the GridPane and the results did not change. The window displays properly and everything else in the application functions. I cannot see any reason this would throw a NullPointerException. Are you guys able to spot something I am missing?

UPDATE
The issue is, in fact, that the getRowIndex() method is returning null for some of the nodes, as pointed out by Bastida. Upon revising the method to the following code, the issue disappeared:

    private Node getNodeFromGridPane(GridPane gridPane, int col, int row) {
        System.out.println("Gridpane: " + gridPane.getChildren().toString());
        for (Node node : gridPane.getChildren()) {
            System.out.println("Node: " + node.toString());
            Integer c = GridPane.getColumnIndex(node);
            c = c == null ? 0 : c;
            Integer r = GridPane.getRowIndex(node);
            r = r == null ? 0 : r;
            if (c == col && r  == row) {
                return node;
            }
        }
        return null;
    }

Thank you.

Zero
  • 71
  • 1
  • 13
  • 1
    So either `GridPane.getColumnIndex(node)` or `GridPane.getRowIndex(node)` returns `null`. Have you tried printing those out? – Zephyr Apr 25 '19 at 23:42
  • 1
    Possible duplicate of [JavaFX: Get Node by row and column](https://stackoverflow.com/questions/20825935/javafx-get-node-by-row-and-column) – Zephyr Apr 25 '19 at 23:50
  • 2
    Be sure to read all the comments for the duplicate question's answer, as it specifically addresses the NPE issue. – Zephyr Apr 25 '19 at 23:51

1 Answers1

1

I think your problem is comparing int with a Integer(It can handle posible null value).

In my opinion you can do this to solve your problem:

Verify that GridPane.getColumnIndex(node) and GridPane.getRowIndex(node) are both another value than null like this:

private Node getNodeFromGridPane(GridPane gridPane, int col, int row) {
System.out.println("Gridpane: " + gridPane.getChildren().toString());
for (Node node : gridPane.getChildren()) {
    System.out.println("Node: " + node.toString());
    if (GridPane.getColumnIndex(node) != null && GridPane.getRowIndex(node) != null &&
        GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
        return node;
    }
}
return null;}

Hope this helped you :)

Bastida
  • 105
  • 1
  • 9
  • 2
    I'd recommend rewriting the check a bit to avoid calling the getters multiple times and properly treat the default value: `Integer cIndex = GridPane.getColumnIndex(node); if (cIndex == null ? col == 0 : cIndex == col) { Integer rIndex = GridPane.getRowIndex(node); if (rIndex == null ? row == 0 : row == rIndex) { return node; }}` – fabian Apr 26 '19 at 08:25
  • They will never be null. The reason for the NPE is the return null at the bottom. The problem is the the comparison of int to Integer this can be solved by changing the parameter to Integer – Matt Apr 26 '19 at 17:23
  • The check is unnecessary – Matt Apr 26 '19 at 17:28