【问题标题】:How to initialize a DataModel in JavaFX如何在 JavaFX 中初始化 DataModel
【发布时间】:2018-11-09 12:48:44
【问题描述】:

我创建了一个基于电子邮件类的数据模型,该类具有一个 IntegerProperty、四个 StringProperty 和一个 Date 作为参数。现在,我试图在我的 ListView 中显示发件人的 ID 和名称,为此我在 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());
            }
        }
    });
}

问题是当我调用这个方法时我得到一个 java.lang.NullPointerException:listView.setItems(model.getEmailList());

这是我的 DataModel 类:

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) { }

}

如何在不以这种方式打开程序后立即填充列表?即使我通过调用 loadData 方法填充它,我也会得到 NullPointerExcpetion。

编辑:这是主要课程:

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:这是 TextAreaController 类:

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());*/
        }
    });
}

}

【问题讨论】:

  • 您应该在您的控制器ListController 中覆盖@FXML private void initialize() {} 并填充(和操作)您的列表。Here 是关于此的文档。尤其是“注”。您还应该将 @FXML 注释添加到 listView 声明中,因为它是私有的。
  • 为了尊重设计模式(例如 MVC 或 MVP)。你不应该在你的控制器中初始化你的模型。
  • 我猜你正在关注@James_D 回答here。我在您的主要内容中没有看到像listController.initModel(model); 这样的代码。如果您在模型上获得NullPointerException,为什么要忽略此代码?你似乎在做listController.initialize(); 并且从未通过模型。
  • 是的,我用那个答案来构建模型。现在我按照下面的答案对其进行了修改。

标签: java listview javafx controller fxml


【解决方案1】:

控制器:

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);
    }
}

型号:

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);
    }
}

数据模型:

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;
    }
}

希望它会起作用。

【讨论】:

  • 我试过了,但没用。我要编辑问题并插入主类,也许错误就在那里。
  • 不只是为他们编写某人的代码,而是解释你改变了什么以及为什么。否则,您的问题对未来的读者来说几乎没有用处。
猜你喜欢
  • 2016-10-27
  • 2018-11-24
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
  • 1970-01-01
  • 2016-03-02
  • 2016-12-22
相关资源
最近更新 更多