【问题标题】:Manually update ListView with a Thread in JavaFX在 JavaFX 中使用线程手动更新 ListView
【发布时间】:2018-12-09 09:45:53
【问题描述】:

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

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

【问题讨论】:

    标签: java multithreading sockets listview javafx


    【解决方案1】:

    你需要把这一行

     listView.setItems(model.getEmailList());
    

    Platform.runLater内:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 2017-04-21
      • 1970-01-01
      • 2015-08-03
      • 1970-01-01
      • 2012-10-03
      • 2014-12-08
      相关资源
      最近更新 更多