JavaFX:无法从匿名类调用Application的Label字段?

时间:2013-06-12 21:11:51

标签: java label javafx

我正在抛弃一个JavaFX应用程序,并试图通过在我的程序后端的Listener表中添加一个匿名类来更改Label的文本。虽然Listener将返回它应该获取的数据,但是当匿名类更改标签时,JavaFX将崩溃。

前端:

public class App extends Application {

...

final BackendElement backendElement = new BackendElement();

...

    @Override
    public void start(Stage mainStage) {

         ...

       GridPane stageContents = generateGridPane(mainStage);

         ...

       mainStage.setScene(new Scene(stageContents));
       mainStage.show();
    }


    private GridPane getGridPane(final Stage mainStage) {

          ...

        final Label labelToBeUpdated = new Label("");

          ...

        backendElement.addModelChangedListener(new ModelChangedListener() {
             @Override
             public void modelChanged(ModelChangedEvent ev) {
                 labelToBeUpdated.setText(ev.getSource()); //<- Causes verbose JFX Exception
             }
        });
    }

ModelChangedListener和ModelChangedEvent只是自定义观察者模式的一部分。由于用简单的

替换错误产生线,结构肯定有效
System.out.println(ev.getSource);

将打印出所需的数据。

我认为私有类'标签不能从匿名类调用。事实证明,App类中的最终字段都不能。有没有办法解决这个问题而不会丢失观察者模式?

这是完整的堆栈跟踪:

Exception in thread "Timer-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = Timer-0
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:237)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:397)
at javafx.scene.Parent$1.onProposedChange(Parent.java:245)
at com.sun.javafx.collections.VetoableObservableList.setAll(VetoableObservableList.java:90)
at com.sun.javafx.collections.ObservableListWrapper.setAll(ObservableListWrapper.java:314)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.updateChildren(LabeledSkinBase.java:602)
at com.sun.javafx.scene.control.skin.LabeledSkinBase.handleControlPropertyChanged(LabeledSkinBase.java:209)
at com.sun.javafx.scene.control.skin.SkinBase$3.changed(SkinBase.java:282)
at javafx.beans.value.WeakChangeListener.changed(WeakChangeListener.java:107)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:196)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.beans.property.StringPropertyBase.fireValueChangedEvent(StringPropertyBase.java:121)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:128)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:161)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:67)
at javafx.beans.property.StringProperty.setValue(StringProperty.java:84)
at javafx.scene.control.Labeled.setText(Labeled.java:135)
at ui.App$12.modelChanged(App.java:349)
at ui.BackendElement$CustomTimerTask.informAllListeners(BackendElement.java:108)
at ui.BackendElement$CustomTimerTask.access$0(BackendElement.java:105)
at ui.BackendElement$CustomTimerTask$1.run(BackendElement.java:87)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)

1 个答案:

答案 0 :(得分:4)

解决方案: 包含你希望听众用Platform.runLater()做的任何事情。

        @Override
        public void modelChanged(ModelChangedEvent ev) {

            final ModelChangedEvent event = ev;

            Platform.runLater(new Runnable(){
                @Override
                public void run() {
                    labelToBeChanged.setText((String)event.getSource());
                }
            });
        }