JavaFX 初始化方法中的 NullPointerException

Posted

技术标签:

【中文标题】JavaFX 初始化方法中的 NullPointerException【英文标题】:NullPointerException in JavaFX initialize method 【发布时间】:2013-02-24 14:24:03 【问题描述】:

我有控制器,我尝试从电子邮件服务器获取 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);
        
    

当我删除 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)

这出现在不同的位置,十四封电子邮件,三十封电子邮件。你有什么想法吗?

p.s 我等不及下载了,因为它需要 20 秒。有 50 封电子邮件 - 我必须在初始化期间执行此操作。

【问题讨论】:

不要用与它们的类相同的大小写来命名变量。 data没有初始化,初始化吧。 我已经初始化了(数据在其他文件中):) 【参考方案1】:

您的错误

不要修改从除 JavaFX 应用程序线程之外的任何其他线程连接到活动场景图的任何内容。

背景信息

有关此规则的说明,请参阅 JavaFX Concurrency Tutorial 和 Usage of JavaFX Platform.runLater and access to UI from a different thread。

由于您的数据列表是 ObservableList 支持活动场景图中显示的 TableView,因此当您修改 ObservableList 时,它会向 TableView 触发更改事件,从您的用户线程而不是 JavaFX 应用程序线程修改它 -这会导致竞争条件和不一致的程序失败。

如何解决

要解决您的问题,请将更新数据项的调用封装在 Platform.runLater 中:

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

提交给Platform.runLaterrun方法的内容在JavaFX应用线程上执行。

【讨论】:

以上是关于JavaFX 初始化方法中的 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

初始化后,在javafx中的控制器之间传递变量[duplicate]

Javafx文本数组未初始化[重复]

Javafx只初始化一次控制器构造函数?

了解javafx中的插值方法

无法从 h2 获取数据

我如何以编程方式从另一种方法单击 JavaFX 中的按钮?