代码之家  ›  专栏  ›  技术社区  ›  JimBelushi2

用javafx中的线程手动更新listview

  •  -1
  • JimBelushi2  · 技术社区  · 6 年前

    我正在开发一个邮箱,我想让客户自动检查是否有新的电子邮件。我通过使用一个线程来实现这一点,该线程循环直到关闭客户机,如果看到列表中当前的电子邮件数量与服务器上的文件数量不同,那么它会重新加载数据并添加新的电子邮件。它是有效的,但是每次我在列表上得到更新时,我都会得到这个例外:

    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 回复  |  直到 6 年前
        1
  •  2
  •   Gnas    6 年前

    你得排这个队

     listView.setItems(model.getEmailList());
    

    里面 Platform.runLater :

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