Обновление ListView с потоком вручную в JavaFX - PullRequest
0 голосов
/ 09 декабря 2018

Я разрабатываю почтовый ящик, и мне бы хотелось, чтобы клиент автоматически проверял наличие новых писем.Я сделал это с помощью потока, который зацикливается до тех пор, пока я не закрою клиент, и если он увидит, что текущее количество электронных писем в списке отличается от количества файлов на сервере, он перезагрузит данные и добавит новое электронное письмо.Это работает, но каждый раз, когда я получаю обновление в списке, я получаю это исключение:

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 Ответ

0 голосов
/ 09 декабря 2018

Вам нужно поместить эту строку

 listView.setItems(model.getEmailList());

внутри Platform.runLater :

 Platform.runLater(() -> listView.setItems(model.getEmailList()));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...