0

I created a Data Model based on an Email class, which has as parameter an IntegerProperty, four StringProperty and a Date. Now, I'm trying to show in my ListView the ID and the name of the sender and to do this I created this method in the ListController:

public class ListController {
private ListView<Email> listView ;

private DataModel model ;

public void initModel(DataModel model) {
    // ensure model is only set once:
    if (this.model != null) {
        throw new IllegalStateException("Model can only be initialized once");
    }

    this.model = model ;
    this.model.loadData(null);
    **listView.setItems(model.getEmailList());**

    listView.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection) -> 
        model.setCurrentEmail(newSelection));

    model.currentEmailProperty().addListener((obs, oldPerson, newPerson) -> {
        if (newPerson == null) {
            listView.getSelectionModel().clearSelection();
        } else {
            listView.getSelectionModel().select(newPerson);
        }
    });

    listView.setCellFactory(lv -> new ListCell<Email>() {
        @Override
        public void updateItem(Email person, boolean empty) {
            super.updateItem(person, empty);
            if (empty) {
                setText(null);
            } else {
                setText(person.getID() + " " + person.getMittente());
            }
        }
    });
}

The problem is that I get a java.lang.NullPointerException when I call this method: listView.setItems(model.getEmailList());

This is my DataModel class:

public class DataModel {

private final ObservableList<Email> emailList = FXCollections.observableArrayList(email -> 
    new Observable[] {email.IDProperty(), email.MittenteProperty()});

private final ObjectProperty<Email> currentEmail = new SimpleObjectProperty<>(null);

public ObjectProperty<Email> currentEmailProperty() {
    return currentEmail ;
}

public final Email getCurrentEmail() {
    return currentEmailProperty().get();
}

public final void setCurrentEmail(Email email) {
    currentEmailProperty().set(email);
}

public ObservableList<Email> getEmailList() {
    return emailList ;
}

public void loadData(File file) {
    // mock...
    emailList.setAll(
            new Email(1, "Smith", "John", "Casa", "BLAAAAAAAAAAAAA", new Date(1997, 3, 2)),
            new Email(2, "Isabella", "Johnson","Bua", "BUUUUUUU", new Date(1995, 6, 2)), 
            new Email(3, "Ethan", "Williams", "Rapporto", "IIIIIIIIII", new Date(2011, 9, 8)), 
            new Email(4, "Emma", "Jones", "Chiesa", "ALEEEEEEEEEE", new Date(2000, 1, 4)), 
            new Email(5, "Pippo", "Brown", "Vignetta", "OSAAAAAAAA", new Date(1987, 4, 5))
    );
}

public void saveData(File file) { }

}

How can I populate the list as soon as I open the program without doing it in this way? I get the NullPointerExcpetion even if I populate it by calling the loadData method.

EDIT: This is the main class:

public class MailBox extends Application {

@Override
public void start(Stage stage) throws Exception {
    BorderPane root = new BorderPane();

    FXMLLoader listLoader = new FXMLLoader(getClass().getResource("lista.fxml"));
    root.setCenter(listLoader.load());
    ListController listController = listLoader.getController();

    FXMLLoader textareaLoader = new FXMLLoader(getClass().getResource("textarea.fxml"));
    root.setBottom(textareaLoader.load());
    TextAreaController textareaController = textareaLoader.getController();

    DataModel model = new DataModel();
    listController.initModel(model);
    textareaController.initModel(model);

    Scene scene = new Scene(root, 355, 402);
    stage.setScene(scene);
    stage.show();
}

EDIT2: And this is the TextAreaController Class:

public class TextAreaController {

private DataModel model;
private TextArea textarea;

public void initModel(DataModel model) {
    if (this.model != null) {
        throw new IllegalStateException("Model can only be initialized once");
    }
    this.model = model ;
    model.loadData(null);//  aggiunto per far caricare i dati delle person
    model.currentEmailProperty().addListener((obs, oldEmail, newEmail) -> {
        if (oldEmail != null) {
            String id = "ID: "+Integer.toString(oldEmail.IDProperty().getValue().intValue())+"\n";
            textarea.setText(id);
            /*firstNameField.textProperty().unbindBidirectional(oldEmail.firstNameProperty());
            lastNameField.textProperty().unbindBidirectional(oldEmail.lastNameProperty());
            emailField.textProperty().unbindBidirectional(oldEmail.emailProperty());*/
        }
        if (newEmail == null) {
            textarea.setText("");
            /*firstNameField.setText("");
            lastNameField.setText("");
            emailField.setText("");*/
        } else {
            String id = "ID: "+Integer.toString(newEmail.IDProperty().getValue().intValue())+"\n";
            textarea.setText(id);
            /*firstNameField.textProperty().bindBidirectional(newEmail.firstNameProperty());
            lastNameField.textProperty().bindBidirectional(newEmail.lastNameProperty());
            emailField.textProperty().bindBidirectional(newEmail.emailProperty());*/
        }
    });
}

}

Samoa Joe
  • 33
  • 1
  • 8
  • You should override `@FXML private void initialize() {}` in your controller `ListController` and populate (and manipulate) your list in. [Here](https://docs.oracle.com/javase/8/javafx/api/javafx/fxml/Initializable.html) is the documentation about that. especially the "Note". You also should add the `@FXML` annotation to the `listView` declaration as it is private. – Pagbo Nov 09 '18 at 13:35
  • 2
    And in order to respect a design pattern (MVC or MVP for example). You should not initialize your model in your controller. – Pagbo Nov 09 '18 at 13:42
  • I am guessing that you are following @James_D answer [here](https://stackoverflow.com/questions/32342864/applying-mvc-with-javafx). What I don't see in your main is code like `listController.initModel(model);`. Why would you leave this code out if you are getting a `NullPointerException` on the model? You seem to be doing `listController.initialize();` and never passing the model. – SedJ601 Nov 09 '18 at 15:17
  • Yeah, I used that answer to build the model. Now I modified it by following the answer down here. – Samoa Joe Nov 09 '18 at 15:22

1 Answers1

-2

Controller:

public class Controller {
    @FXML
    private ListView<Email> listView;
    private DataModel model = new DataModel();

    @FXML
    private void initialize() {
         List<Email> emailList = model.loadData();
         listView.getItems().addAll(emailList);
    }
}

Model:

public class Email {
    int id;
    String firstProperty;
    String secondProperty;
    String thirdProperty;
    String fourthProperty;
    Date date;

    public Email(int id, String firstProperty, String secondProperty, String thirdProperty, String fourthProperty, Date date) {
         this.id = id;
         this.firstProperty = firstProperty;
         this.secondProperty = secondProperty;
         this.thirdProperty = thirdProperty;
         this.fourthProperty = fourthProperty;
         this.date = date;
    }

    @Override
    public String toString(){
        return ("ID: " + this.id + ", Name: " + this.firstProperty);
    }
}

DataModel:

public class DataModel {
    public List<Email> loadData() {

        List<Email> emailList = new ArrayList<>();

        emailList.addAll(
                Arrays.asList(
                        new Email(1, "Smith", "John", "Casa", "BLAAAAAAAAAAAAA", new Date(1997, 3, 2)),
                        new Email(2, "Isabella", "Johnson", "Bua", "BUUUUUUU", new Date(1995, 6, 2)),
                        new Email(3, "Ethan", "Williams", "Rapporto", "IIIIIIIIII", new Date(2011, 9, 8)),
                        new Email(4, "Emma", "Jones", "Chiesa", "ALEEEEEEEEEE", new Date(2000, 1, 4)),
                        new Email(5, "Pippo", "Brown", "Vignetta", "OSAAAAAAAA", new Date(1987, 4, 5))
                )
        );

        return emailList;
    }
}

Hope it will work.

  • I tried but it didn't work. I'm gonna edit the question and inserting the main class, maybe the error is there. – Samoa Joe Nov 09 '18 at 15:04
  • 1
    Instead of just writing someone’s code for them, explained what you changed and why. Without that, your question is of little or no use to future readers. – VGR Nov 09 '18 at 16:49