简体   繁体   English

JavaFX初始化方法中的NullPointerException

[英]NullPointerException in JavaFX initialize method

I have controller and there I trying get INBOX folder from e-mail server. 我有控制器,我尝试从电子邮件服务器获取INBOX文件夹。 With downloading everything is ok. 下载一切都很好。 I can put this data(email subject,from,date) into TableView but... only when I am waiting for thread responsible for set this data in TableView. 我可以把这些数据(电子邮件主题,从,日期)放到TableView中但是......只有当我在等待负责在TableView中设置这些数据的线程时。 Code: 码:

// The table and columns
@FXML
TableView<MainModel.Item> itemTbl;
@FXML
TableColumn itemNameCol;
@FXML
TableColumn itemQtyCol;
@FXML
TableColumn itemTitleCol;
// The table's data
static ObservableList<MainModel.Item> data;

public void dataSet(){
    // Set up the table data
    itemNameCol.setCellValueFactory(
        new PropertyValueFactory<MainModel.Item,String>("name")
    );
    itemQtyCol.setCellValueFactory(
        new PropertyValueFactory<MainModel.Item,String>("qty")
    );
    itemTitleCol.setCellValueFactory(
        new PropertyValueFactory<MainModel.Item,String>("title")
    );

    data = FXCollections.observableArrayList();
    itemTbl.setItems(data);
}

public void setEnemyEvent() {
    itemTbl.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            if (event.getClickCount() == 2) {
                if(itemTbl.getSelectionModel().getSelectedItem()!=null){
                    System.out.println(itemTbl.getSelectionModel().getSelectedItem().name);
                }
            }
        }
    });
}

@Override
public void initialize(URL url, ResourceBundle rb) { 
    setEnemyEvent();
    dataSet();
    Thread t = new Thread(new MessageLoop());
    //HERE:
    t.start();
    //of course normally here is try and catch
    t.join();
}

//staric nested class "for loop"
private static class MessageLoop implements Runnable {
    public void run() {
        try {
            EmailConnetion con = new EmailConnetion();
            MainModel MainModel = new MainModel();
            for(int i=0;i<con.message.length;i++){
                try{
                    MainModel.Item item = MainModel.new Item();
                    item.name.setValue(i+""+con.message[i].getFrom()[0].toString());
                    item.qty.setValue(con.message[i].getSentDate().toString());
                    item.title.setValue(con.message[i].getSubject().toString());
                    //Here is a problem.
                    data.add(item);//This indicate my IDE  
                    //*****************
                } catch(AddressException e) {
                    System.out.println("Error : " + "AddressException:"+i);
                }
            }
        } catch (NoSuchProviderException ex) {
            Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (MessagingException ex) {
            Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

When i remove t.join() it will throw this NullPointerException. 当我删除t.join()时,它将抛出此NullPointerException。

Exception in thread "Thread-3" java.lang.NullPointerException
    at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:291)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
    at com.sun.javafx.scene.control.ReadOnlyUnbackedObservableList.callObservers(ReadOnlyUnbackedObservableList.java:74)
    at javafx.scene.control.TableView$TableViewArrayListSelectionModel$3.onChanged(TableView.java:1725)
    at com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:134)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
    at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
    at com.sun.javafx.collections.ObservableListWrapper.clear(ObservableListWrapper.java:184)
    at javafx.scene.control.TableView$TableViewArrayListSelectionModel.quietClearSelection(TableView.java:2154)
    at javafx.scene.control.TableView$TableViewArrayListSelectionModel.updateSelection(TableView.java:1902)
    at javafx.scene.control.TableView$TableViewArrayListSelectionModel.access$2600(TableView.java:1681)
    at javafx.scene.control.TableView$TableViewArrayListSelectionModel$8.onChanged(TableView.java:1802)
    at com.sun.javafx.scene.control.WeakListChangeListener.onChanged(WeakListChangeListener.java:71)
    at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(ListListenerHelper.java:291)
    at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:48)
    at com.sun.javafx.collections.ObservableListWrapper.callObservers(ObservableListWrapper.java:97)
    at com.sun.javafx.collections.ObservableListWrapper.add(ObservableListWrapper.java:154)
    at com.sun.javafx.collections.ObservableListWrapper.add(ObservableListWrapper.java:144)
    at javasplitpane.SimpleController$MessageLoop.run(SimpleController.java:95)
    at java.lang.Thread.run(Thread.java:722)

This appear in different position, in fourteen email, thirty email. 这出现在不同的位置,十四封电子邮件,三十封电子邮件。 You have some ideas ? 你有一些想法吗?

ps I can't wait for this downloading because it takes 20 sec. ps我不能等待下载,因为它需要20秒。 with 50 emails - I have to do it during initialize. 有50封电子邮件 - 我必须在初始化期间执行此操作。

Your Error 你的错误

Don't modify anything which is connected to the active scene graph from any other thread than the JavaFX Application Thread. 不要从JavaFX应用程序线程之外的任何其他线程修改连接到活动场景图的任何内容。

Background Information 背景资料

See the JavaFX Concurrency Tutorial and also Usage of JavaFX Platform.runLater and access to UI from a different thread for an explanation of this rule. 有关此规则的说明,请参阅JavaFX Concurrency Tutorial以及JavaFX Platform.runLater的用法以及从其他线程访问UI

As your data list is an ObservableList backing a TableView displayed in the active scene graph, as you modify the ObservableList, it fires change events to the TableView modifying it from your user thread rather than the JavaFX Application Thread - this causes race conditions and inconsistent program failures. 随着数据列表是一个ObservableList来头TableView中显示在活动场景图,为您修改ObservableList,他们就触发改变事件的TableView中从用户线程,而不是JavaFX应用程序线程修改它-这将导致竞争和不一致的程序故障。

How to Fix it 如何解决它

To fix your issue, wrap the call to update the data item inside Platform.runLater : 要解决您的问题,请将调用包装为更新Platform.runLater中的数据项:

Platform.runLater(new Runnable() {
  @Override public void run() {
    data.add(item);
  }
});

The contents of the run method submitted to Platform.runLater are executed on the JavaFX Application Thread. 提交给Platform.runLaterrun方法的内容在JavaFX Application Thread上执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM