首页 文章

使用JavaFX中的线程手动更新ListView

提问于
浏览
0

我正在开发一个邮箱,我希望客户端自动检查是否有新的电子邮件 . 我通过使用一个循环直到我关闭客户端并且如果看到列表上的当前电子邮件数量与服务器上的文件数量不同而重新加载数据并添加新电子邮件 . 它有效,但每次我在列表上获得更新时,我都会遇到这个异常:

Exception in thread "Thread-5" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-5
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:279)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:423)
at javafx.scene.Parent$2.onProposedChange(Parent.java:367)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:113)
at com.sun.javafx.collections.VetoableListDecorator.setAll(VetoableListDecorator.java:108)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:575)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:204)
at com.sun.javafx.scene.control.skin.ListCellSkin.handleControlPropertyChanged(ListCellSkin.java:49)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase.lambda$registerChangeListener$61(BehaviorSkinBase.java:197)
at com.sun.javafx.scene.control.MultiplePropertyChangeListenerHandler$1.changed(MultiplePropertyChangeListenerHandler.java:55)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:103)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:110)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:144)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:49)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:65)
at javafx.scene.control.Labeled.setText(Labeled.java:145)
at mailbox.ListController$1.updateItem(ListController.java:56)
at mailbox.ListController$1.updateItem(ListController.java:49)
at javafx.scene.control.ListCell.updateItem(ListCell.java:471)
at javafx.scene.control.ListCell.access$300(ListCell.java:72)
at javafx.scene.control.ListCell$2.changed(ListCell.java:185)
at javafx.scene.control.ListCell$2.changed(ListCell.java:175)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:89)
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:361)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:105)
at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
at javafx.scene.control.ListView.setItems(ListView.java:390)
at mailbox.ListController$2.run(ListController.java:71)

这是我的ListView控制器代码:

public class ListController {

@FXML
private ListView<Email> listView;
private DataModel model;
private int NoE;

public void initModel(DataModel model) throws IOException, ClassNotFoundException, ParseException {
    if (this.model != null) {
        throw new IllegalStateException("Model can only be initialized once");
    }
    this.model = model;

    model.loadData();

    listView.setItems(model.getEmailList());

    listView.getSelectionModel().selectedItemProperty().addListener((obs, oldSelection, newSelection)
            -> model.setCurrentEmail(newSelection));
    model.currentEmailProperty().addListener((obs, oldEmail, newEmail) -> {
        if (newEmail == null) {
            listView.getSelectionModel().clearSelection();
        } else {
            listView.getSelectionModel().select(newEmail);
        }
    });

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

    NoE = model.getNumberOfEmail();
    new Thread() {
        @Override
        public void run() {
            while (true) {
                try {
                    int current = model.askNumbOfEmail();
                    if (NoE != current) {
                        NoE = current;
                        model.reLoadData();
                        listView.setItems(model.getEmailList());
                    }
                } catch (IOException ex) {
                    Thread.currentThread().interrupt();
                    return;
                } catch (ParseException ex) {
                    System.out.println("ParseException ERROR!");
                }
            }
        }
    }.start();
  }
}

1 回答

  • 2

    你需要把这一行

    listView.setItems(model.getEmailList());
    

    Platform.runLater内:

    Platform.runLater(() -> listView.setItems(model.getEmailList()));
    

相关问题