java JavaFX 初始化方法中的 NullPointerException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15304203/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
NullPointerException in JavaFX initialize method
提问by user2150038
I have controller and there I trying get INBOX folder from e-mail server. 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. Code:
我有控制器,在那里我尝试从电子邮件服务器获取 INBOX 文件夹。下载后一切正常。我可以将此数据(电子邮件主题、发件人、日期)放入 TableView 但...仅当我等待负责在 TableView 中设置此数据的线程时。代码:
// 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.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.access00(TableView.java:1681)
at javafx.scene.control.TableView$TableViewArrayListSelectionModel.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 ?
这出现在不同的位置,在十四封电子邮件,三十封电子邮件。你有什么想法吗?
p.s I can't wait for this downloading because it takes 20 sec. with 50 emails - I have to do it during initialize.
ps 我等不及这个下载了,因为它需要 20 秒。有 50 封电子邮件 - 我必须在初始化期间完成。
回答by jewelsea
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 Tutorialand also Usage of JavaFX Platform.runLater and access to UI from a different threadfor an explanation of this rule.
有关此规则的说明,请参阅JavaFX 并发教程以及JavaFX Platform.runLater 的用法和从不同线程访问 UI。
As your data list is an ObservableListbacking a TableViewdisplayed 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.
由于您的数据列表是支持显示在活动场景图中的TableView的ObservableList,当您修改 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.
run
提交到的方法的内容Platform.runLater
在 JavaFX 应用程序线程上执行。