Javafx修改"标签"在SwingUtilities.invokeLater中

时间:2016-10-11 17:09:41

标签: java javafx pane swingutilities

我想做以下事情:

  1. 点击按钮
  2. 将矩形颜色设为
  3. 等待1秒
  4. 颜色为矩形蓝色
  5. 在以下代码中:

    GraphicsContext gc;
    Button myButton = new Button("Button!");
    myButton.setOnAction(new EventHandler<ActionEvent>(){
            @Override
            public void handle(ActionEvent event){
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        gc.setFill(Color.RED);
                        gc.fillRect(0, 0, 100, 100);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                        }
                        gc.setFill(Color.BLUE);
                        gc.fillRect(0, 0, 100, 100);
                    }
                });
            }
        });
    

    这很好用。它创建一个0,0的红色框,宽度和宽度为0。高度为100.但是当我尝试修改一个标签时,它会崩溃。

    GraphicsContext gc;
    Pane root = new Pane();
    Button myButton = new Button("Button!");
    Label myLabel = new Label("HELLO!"); // added
    root.getChildren.add(myLabel);
    myButton.setOnAction(new EventHandler<ActionEvent>(){
            @Override
            public void handle(ActionEvent event){
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        gc.setFill(Color.RED);
                        gc.fillRect(0, 0, 100, 100);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                        }
                        gc.setFill(Color.BLUE);
                        gc.fillRect(0, 0, 100, 100);
                        myLabel.setText("WORLD!"); // modified here
                    }
                });
            }
        });
    

    我期待的结果是,

    1. 点击按钮

    2. 将矩形颜色设为

    3. 等待1秒

    4. 将矩形颜色设为

    5. 然后更改HELLO的标签文字!世界!

    6. 但是我收到了错误。为什么会这样?我可以不修改SwingUtilities中的任何Pane元素吗?

      任何建议都会有所帮助。

      修改

      这是我按下按钮时出现的错误

      Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Not on FX application thread; currentThread = AWT-EventQueue-0
      at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:229)
      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.LabelSkin.handleControlPropertyChanged(LabelSkin.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 Lego$1$1.run(Lego.java:63)
      at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
      at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
      at java.awt.EventQueue.access$500(EventQueue.java:97)
      at java.awt.EventQueue$3.run(EventQueue.java:709)
      at java.awt.EventQueue$3.run(EventQueue.java:703)
      at java.security.AccessController.doPrivileged(Native Method)
      at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
      at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
      at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
      at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
      

2 个答案:

答案 0 :(得分:3)

这是因为任何Java FX components必须由JavaFX Application Thread管理,因为它们不是线程安全的(这与任何Swing components必须完全相同的原因由AWT event dispatching Thread管理,因此您需要使用Platform.runLater(runnable)作为下一个间接修改您的标签:

使用Java 8

Platform.runLater(() -> myLabel.setText("WORLD!"));

使用以前版本的Java

Platform.runLater(new Runnable() {
        public void run() {
            myLabel.setText("WORLD!"); 
        }
    }
);

我们使用SwingUtilities.invokeLater(runnable)AWT event dispatching thread执行一些将在未来某个未指定的时间修改Swing components的代码,如果Platform.runLater(runnable)Java FX components相同Swing

NB:仅使用Java FX个组件或仅使用Swing个组件,除非您没有其他选择,否则请避免混用JavaFXlm(1_T1 ~ CRP, data = exposure)个组件。

答案 1 :(得分:1)

永远不要暂停JFXAT,不要在它上面睡觉,你要杀死响应,创建一个线程,在它上面睡觉,然后在里面使用Platform.runLater来更新UI。

updateLbl(){
    new Thread(new Runnable(){
         Thread.sleep();//sleep //try catch
         Platform.runLater ... //inside update ui
    }).start();
}