2

Seems like a rarely asked question, so maybe extending GridPane is the wrong approach altogether. I did look at How to extend custom JavaFX components that use FXML and more.

I am trying to create a LawnGrid class that extends GridPane, the reason is to override the add() method to resize ImageView nodes as they are added. I also need to resize based on calculating the size of the LawnGrid and figuring out whether the lawn is wider than it is high, wanting to preserve an aspect ratio. I am leaving out details of implementation that seem irrelevant.

The problem is when I put a LawnGrid into the .fxml file it won't show in SceneBuilder (in IntelliJ) which I think is a symptom of what I am doing wrong. I get this error:

java.lang.NullPointerException / javafx.fxml.LoadException:

which points to my view.fxml: ... (inside a BorderPane)

<center>
    <LawnGrid fx:id="lawnGridPane" style=" -fx-border-color:green; -fx-border-width: 10; -fx-border-style: solid;" BorderPane.alignment="CENTER">

    </LawnGrid>
</center>

I want to add the constraints programmatically, maybe I need them up front but it seems like I would get a different error. Based on linked answer above, my LawnGrid.java starts with:

@DefaultProperty(value = "lawnGrid")
public class LawnGrid extends GridPane {

UPDATE: Based on Slaw's feedback I see the mistake of having the FXML annotation in the wrong place, moved it to my FXController.java:

// lawn representation for lawn display in GUI
    @FXML
    private LawnGrid lawnGridPane = new LawnGrid();

FWIW I also get a NPE when I try to run it, the application appears but gives NPE on a line where I refer to "this" inside LawnGrid. I assume I am missing something fundamental about how JavaFX instantiates objects and need to create the LawnGrid somewhere but I thought the .fxml file set this up.

EDIT: I did add super() to my constructors thinking that might make some difference but it didn't, I believe just by using extends it calls super()? Here's the constructors in LawnGrid.java:

   public LawnGrid(){
        super();
        // uses default max 10 rows 15 columns
        setupLawnConstraints();
    }

    public LawnGrid(double rows, double columns){
        super();
        this.numRows = rows;
        this.numCols = columns;
        setupLawnConstraints();
    }

    public LawnGrid(double rows, double columns, DoubleProperty preferredSquareSizeProperty) {
        super();
        this.numRows = rows;
        this.numCols = columns;
        this.preferredSquareSizeProperty = preferredSquareSizeProperty;
    }
Makoto
  • 104,088
  • 27
  • 192
  • 230
JimLohse
  • 1,209
  • 4
  • 19
  • 44
  • Couple of things might help improve your question (and thus make answering easier). (1) Instead of adding updates to your code at the end of your question, show the updates in the original code to avoid confusion. If you're no longer using the old code there's no reason for us to see it. (2) Try to create and post a [mcve] demonstrating the issue. Include the stack trace of the NPE. We need more information on where the exception is occurring and how that code is executed. – Slaw Mar 31 '19 at 21:14
  • If the NPE is occurring inside `LawnGrid`, note that you only appear to initialize `preferredSquareSizeProperty` in the third constructor. Your FXML snippet shows no indication of initializing the property (it'll likely use the no-arg constructor), so it's possible that might be `null`. Also, giving an instance of `DoubleProperty` to your class seems wrong. Why not have it as a property of the class and simply set it or bind it to some other property? – Slaw Mar 31 '19 at 21:26
  • Not exactly related to your actual question.. if your only purpose of overriding add() method is to resize the ImageViews I assume you can do that by adding a listener to gridPane.getChildren(). Just a thought without knowing your other requirements :) – Sai Dandem Mar 31 '19 at 22:06
  • @Slaw thanks again I heavily edited this question after undeleting and you can see the answer below, this was obvious and obscure at the same time -- at least to me. Hope this helps someone else. – JimLohse Apr 01 '19 at 16:45
  • You're not really meant to change the actual *question* you post. If you want to document it, you should put all relevant information/facts into your *answer*. Since you're active right now I'll give you a chance to do that, but know that I'll roll back this question in a few hours' time. – Makoto Apr 01 '19 at 16:45
  • Oh ok thanks I thought the original question had a lot of irrelevant stuff given the answer. I don't have the original content (do I?) so please feel free to roll it back, will my answer be lost? Also feel free to delete again and I'll be fine with whatever you do. – JimLohse Apr 01 '19 at 16:47
  • The answer will stay, but the question will be restored to what it was when you had added those details. It'll remain in the edit history so if you want to bring anything over from that you can. – Makoto Apr 01 '19 at 16:54
  • Thanks again looks to me (tested in Incognito window as well) that you rolled it back, I learned a lot here. I appreciate it – JimLohse Apr 01 '19 at 16:58

1 Answers1

1

In the end, I was calling getHeight on a GridPane (or a subclass of one). When I finally cleared my head and really thought about it, I inspected the object right before it broke.

Some properties of JavaFX objects are null if they are not previously set. Accessing them with getHeight() leads to a (correct) Null Pointer Exception.

"height" is one of them, there is a "_height" but I haven't figured out how to access that.

JimLohse
  • 1,209
  • 4
  • 19
  • 44