0

I came across some documents on internet that in javafx you can apply controller to only parent element.

I have a javafx application (built with scenebuilder, eclipse) which has basic structure like this :

SplitPane
{
     AnchorPane
     {

     }
     AnchorPane
     {
          GridPane
          {
               Pane
               {
                     Label
                     {

                     }
               }
               Pane
               {
                     Label
                     {

                     }
               }
          }
     }
}

I want to change the values of those labels at runtime. But it is throwing java.lang.NullPointerException. My assumption why this is hapening is I'm applying controller to split pane and the labels are not direct children of it so I can't access them.

So questions are : 1) Is my assumption correct ? If not where I'm wrong or missing something ?

2) How to access the labels ?

3) Can I use controller for inner elements (not parent) ?

Thanks in advance, and sorry if the question doesn't make any sense, I'm very very new to javafx.

UPDATE : HERE'S THE CODE i'M USING AND EXCEPTION STACK TRACE :

 public class Controller implements Initializable 
    {
        @FXML
        private SplitPane splitPane;

        @FXML
        private AnchorPane anchorPane1;

        @FXML
        private AnchorPane anchorPane2;

        @FXML
        private GridPane gridPane;

        @FXML
        private static Label z1;
        @FXML
        private static Label z2;
        private HashMap<Integer,Label> zoneLabelNames = new HashMap<Integer,Label>();
        public Controller()
        {
        // I have around 20 such labels which's value i'm setting using a loop. For now I've writter two only.
        zoneLabelNames.put(0, z1);
        zoneLabelNames.put(1, z2);
         new Thread(() -> {
                while(true)
                {
                    try
                    {
                        //some logic to generate new values which will update labels
                        Platform.runLater(() -> {
                            //here I'm actually setting values in loop, for now I wrote only two labels.
                            for(int i =0;i<2;i++)
                            {
                                zoneLabelNames.get(i).setText("newly generated value"); // nullPointerException at this line
                            }
                        });
                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
Amol.Shaligram
  • 713
  • 1
  • 5
  • 12
  • Edit your question and include the entire stack trace of the NullPointerException, and include the code which generated that exception. – VGR Jun 27 '18 at 14:37
  • You can first get the root `SplitPane`. Then get its children. Then get the `AnchorPane` with with `children.size > 0`. Then get the `Gridpane`. Then get all of its `Pane`. Finally get the `Pane's` child. I would not recommend this approach. You should assign each node a `fx:id`. – SedJ601 Jun 27 '18 at 14:57
  • @Sedrick I thought of this approach of getting childrens, but couldn't find `getChildren()` method for `SplitPane`. Also I've assigned `fx:id` to each element, to each `SplitPane`, `AnchorPane`, `GridPane`, `Pane` and `Label`. Still getting the `nullPointerException`. – Amol.Shaligram Jun 27 '18 at 15:16
  • Did you try `SpltPane.getItems`? – SedJ601 Jun 27 '18 at 15:43
  • Why `static` on the `Labels`? – SedJ601 Jun 27 '18 at 15:55
  • null pointer exception again. is it necessary to have fields for all the children and subchildren of the splitPane ? because I've created fields for only those children and subchildren which i want to access at runtime. – Amol.Shaligram Jun 27 '18 at 15:56
  • I removed static. Also when I access the field label individually, it's working but not when i take it from HashMap. Any solution for that ? – Amol.Shaligram Jun 27 '18 at 16:01

1 Answers1

4

To answer your questions:

1) You can access them if you're creating an FXML file. See point 2.

2) If you are wanting to access the Labels at runtime, you can put an attribute on them in the FXML file you're loading like so: fx:id="_label1". Then in your controller class, you are able to create a field for that Label like so: @FXML private Label _label1;

3) You cannot add a controller to another element other than the root element of the FXML file. If you would like to have a controller on a specific element of the FXML, you have to use an <fx:include source="..."/> tag. See documentation

I highly recommend that you read through a tutorial on FXML and JavaFX such as the one from Oracle: https://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm

Blake Ordway
  • 308
  • 1
  • 8
  • Yes, I'm creating an FXML file. Also I've your second point implemented.but still it's throwing nullPointerException. Can you please check the code I've updated and response back ? Thanks !! – Amol.Shaligram Jun 27 '18 at 15:13
  • I'm not sure how you're initializing your class, but if you've linked the class to the FXML file, you probably don't need to have a constructor--you may need one if you have to pass params, but that's a different discussion. Try swapping your constructor to another method: `@FXML public void initialize(){ ... }` – Blake Ordway Jun 27 '18 at 16:05
  • `@Override public void initialize(URL arg0, ResourceBundle arg1) { }` What should i pass here for arg0 and arg1 ? and from where ? this is auto generated method. – Amol.Shaligram Jun 27 '18 at 16:09
  • Use the one I just commented, not that one. The `initialize()` function is called by FXML after the FXML file is loaded and all the variables are created. You should also post how you're generating this controller class in your code, because that is probably one reason why you get a null pointer. – Blake Ordway Jun 27 '18 at 16:21
  • I'll surely try that sometime later. Thanks for that. But for now i fugured out thta exception occured at the line inside the for loop where I'm fetching the label from hashmap and then calling the `setText()` method. So when I do `z1.setText()` it works, but when I do ` zoneLabelNames.get(i).setText();`, throws a nullPointerException. Can you please tell proper way to access it with hashmap ? I can't access them individually because there are too many labels (around 20-25). – Amol.Shaligram Jun 27 '18 at 16:29
  • You can use an `ArrayList` instead and that will allow you to access the `Label`s with an integer value in the `get()` method. Similar to an array – Blake Ordway Jun 27 '18 at 16:44
  • Tried with `ArrayList`, still throwing nullpointer exception. – Amol.Shaligram Jun 27 '18 at 17:09
  • Check this: https://stackoverflow.com/questions/21502430/static-fxml-variables-in-fxml-controller – Blake Ordway Jun 27 '18 at 17:40
  • It worked for me, I just moved whatever I was doing in constructor to overridden `initialize()` method. Constructor is surely not a place to initialize the injected variables. Any one coming here looking for solution, please DON'T TRY TO INITIALIZE ANYTHING IN CONSTRUCTOR EVER. Like a stupid I wasted 4 days on this. – Amol.Shaligram Jun 28 '18 at 17:10