-2

I have a ViewController class and a TabController class. TabController extends ViewController.

In the ViewController I make the Tabs dynamically and I would like to change the name of the Tab at some point. I am always getting Null Pointer...

ViewController class

public class ViewController implements Initializable {

    @FXML
    private TabPane tabPane;
    @FXML
    private Button addNewTabButton;

    private Integer count = 1;

    private SingleSelectionModel<Tab> selectionModel;

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {
        selectionModel = tabPane.getSelectionModel();
    }

    @FXML
    public void createNewTab(){
        Tab newTab = new Tab();
        try {
           String id = count.toString();

           newTab.setText("New Tab");
           newTab.setClosable(true);
           newTab.setId(id);
           newTab.setContent(FXMLLoader.load(getClass().getResource("Tab.fxml")));
           count++;

        } catch (IOException e){
            System.out.println("Error");
        }
            tabPane.getTabs().add(newTab);
       selectionModel.selectLast();
    }

    public void setTabText(String text){
        selectionModel.getSelectedItem().setText(text);
    }
}

TabController class

public class TabController extends ViewController implements Initializable {

    @FXML
    private Button setTextButton;

    @FXML
    private void fooBar(){
        setTabText("fooBar");
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }
}

I am always getting NullPointer on the line: setTabText("fooBar"); (TabControllerClass)

The problem is exist if I want to reach the setTabText() method from the TabController class. (There is no error when I am calling the setTabText() within the ViewController).

Thank you for your help!

c0der
  • 18,467
  • 6
  • 33
  • 65
Balazs
  • 1
  • 4
  • 2
    Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Zephyr Jul 03 '19 at 02:14
  • I recommend studying up more on inheritance. Though you're calling `setTabText()` from a class that extends `ViewController`, your `TabController` class does not **have** a `selectionModel` object. You declare a variable for it in `ViewController`: `private SingleSelectionModel selectionModel;` but never instantiate it within `TabController`. Basically, you do not inherit all the code from a parent class; you only get instance fields and methods. – Zephyr Jul 03 '19 at 02:18
  • To add to what @Zephyr wrote: specifically `TabController` does not invoke `ViewController` initialize method. See my detailed answer. – c0der Jul 03 '19 at 06:41

1 Answers1

1

To followup what is going on, add a simple print message to ViewController initialize method:

  public void initialize(URL location, ResourceBundle resources)
    {
        selectionModel = tabPane.getSelectionModel();
        System.out.println("ViewController initialized");
    }

When you use ViewController it prints out as expected.
When you use TabController it does not. This explains why selectionModel is not initialized, and why you get NPE.

One solution is to have TabController initialize its super :

@Override
public void initialize(URL url, ResourceBundle rb) {
    super.initialize(url, rb);
} 

Here is a simple mcve to demonstrate it *

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class Test1 extends Application
{

    @Override
    public void start(Stage primaryStage) {
        try {
            Pane page = (Pane) FXMLLoader.load(this.getClass().getResource("test1.fxml"));
            Scene scene = new Scene(page);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

test1.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane prefHeight="200.0" prefWidth="200.0" xmlns="http://javafx.com/javafx/10.0.1" 
xmlns:fx="http://javafx.com/fxml/1" fx:controller="TabController">
   <center>
      <TabPane fx:id="tabPane" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER" />
   </center>
   <bottom>
      <Button fx:id="addNewTabButton" mnemonicParsing="false" onAction="#createNewTab" text="Button" BorderPane.alignment="CENTER" />
   </bottom>
</BorderPane>

Simplified controllers:

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.SingleSelectionModel;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.text.Text;

public class ViewController implements Initializable {

    @FXML
    private TabPane tabPane;
    @FXML
    private Button addNewTabButton;

    private int count = 1;

    private SingleSelectionModel<Tab> selectionModel;

    @Override
    public void initialize(URL location, ResourceBundle resources)
    {
        selectionModel = tabPane.getSelectionModel();
        System.out.println("ViewController initialized");
    }

    @FXML
    public void createNewTab(){
       Tab newTab = new Tab();
       String id = String.valueOf(count++);
       newTab.setText(id);
       newTab.setContent(new Text("Tab number "+id));
       tabPane.getTabs().add(newTab);
       selectionModel.selectLast();
    }

    public void setTabText(String text){
        selectionModel.getSelectedItem().setText(text);
    }
}


import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;

public class TabController extends ViewController implements Initializable {

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        super.initialize(url, rb); //comment out this line to cause NPE
    }
}


* Consider posting mcve when asking. It makes helping easier and quicker.
c0der
  • 18,467
  • 6
  • 33
  • 65
  • Thank you, but this is already working, now I want to achive, that I would like to give text to the tab, when it is already created. So, I have 1 more button, which should be in the TabController, since I have a text in TabController, what have to be the name of the tab. – Balazs Aug 27 '19 at 00:45
  • I mean this solutions outcome is almost the same then mine. I want to achive, that I would like to give text to the tab, when it is already created. So, I have 1 more button, which should be in the TabController, since I have a text in TabController, what have to be the name of the tab – Balazs Aug 28 '19 at 22:56
  • This is not new question... this is my original question – Balazs Sep 02 '19 at 19:46