1

I am trying to change one of my columns and its cell values from another class however i keep getting a null pointer exception when java try's to execute that line OverviewController.getOverviewController.returnStatusColumn.setCellValueFactory( cellData -> cellData.getValue().getStatusProperty());, I have removed all irreverent code

TableView Class:

@FXML 
private TableView<Task> taskTable;
@FXML
private TableColumn<Task, String> statusColumn;

private final static OverviewController controller = new OverviewController 
();


public static OverviewController getOverviewController() {
    return controller;
}


public void setMainApp(MainApp mainApp) {
    this.mainApp = mainApp;
    taskTable.setItems(mainApp.getTaskData());
    taskTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    taskTable.setPlaceholder(new Label(""));
}

public TableView<taskTable> returnTasks() {
    return taskTable;
}

public TableColumn<taskTable, String> returnStatusColumn() {
    return statusColumn;
}

@Override
public void initialize(URL location, ResourceBundle resources) {
        statusColumn.setCellValueFactory(cellData -> 
cellData.getValue().getStatusProperty());
}

@FXML
public void createTask(ActionEvent event) throws InterruptedException, 
IOException, ParseException {
    thread = new MyThread();
    thread.main(null);

    statusColumn.setCellValueFactory(cellData -> 
cellData.getValue().getStatusRunningProperty());
    statusColumn.setStyle("-fx-text-fill: green; -fx-font-weight: bold;");
    taskTable.refresh();
}

@FXML
public void stopTasks() {
    statusColumn.setCellValueFactory(cellData -> 
cellData.getValue().getStatusProperty());
    statusColumn.setStyle("-fx-text-fill: red; -fx-font-weight: bold;");
    taskTable.refresh();
}

This class works fine when i want to update the table columns, if i click stop tasks method (which is linked to a button) the status column gets updated to the stop label which i want to do, same with start tasks method.

Random class where i want to update the Table view status column:

public class UpdateTable {
public static void main(String[] args) {
    OverviewController.getOverviewController.returnStatusColumn.setCellValueFactory(
    cellData -> cellData.getValue().getStatusProperty());
    OverviewController.getOverviewController().returnTasks().refresh();
    }

}

TableView Data:

//Status Information
private final SimpleStringProperty status;
private final SimpleStringProperty statusRunning;


public Task() {
    this(null, null);
}

    public Task() {
        this.statusRunning = new SimpleStringProperty("Running");
        this.status= new SimpleStringProperty("Stop");
    }

    public StringProperty getStatusProperty( ) {
        return status;
    }

    public StringProperty getStatusRunningProperty( ) {
        return statusRunning;
    }

}

If i ran the random class it will lead to a null pointer exception in particular this line: OverviewController.getOverviewController().returnStatusColumn().setCellValueFactory(cellData -> cellData.getValue().getStatusProperty());

Have i done this completely the wrong way? I just want to be able to update the Table view column cells from a different class.

DrExpresso
  • 73
  • 1
  • 7
  • a general rule: if you seem to need static fields you are doing something wrong, always (as in 99.999999%) – kleopatra Aug 25 '18 at 12:36

1 Answers1

2

Yes, you're doing this the wrong way.

You don't use a Application subclass anywhere which needs to be used as entry point of your application (assuming you're not using JFXPanel or Platform.startup). Furthermore you access the column as first statement in your program which means there's no way the statusColumn field is initialized.

Also usually there shouldn't be a need to involve any class but the controller class for initializing the cellValueFactory. Especially using static fields is a bad approach:

Assuming you specify the controller class in the fxml, FXMLLoader creates a new instance of the controller class. This instance is different from the instance stored in the controller field so even when using

OverviewController.getOverviewController.returnStatusColumn.setCellValueFactory(
    cellData -> cellData.getValue().getStatusProperty());

after loading the fxml you wouldn't get the instance you need.

Instead I recommend using the initialize method of the controller class for these kind of initialisations. It's invoked by FXMLLoader after creating and injecting all the objects specified in the fxml.

public class OverviewController {

    ...

    @FXML
    private TableColumn<Task, String> statusColumn;

    ...

    @FXML
    private void initialize() {
        statusColumn.setCellValueFactory(cellData -> cellData.getValue().getStatusProperty());
    }

}

If you do need to pass some info from an class that is not the controller, refer to the answers here Passing Parameters JavaFX FXML . Better approaches than using static are described in the answers.

fabian
  • 80,457
  • 12
  • 86
  • 114