Javafx 修改 SwingUtilities.invokeLater 中的 "Label"

标签 java javafx pane swingutilities

我想做以下事情:

  1. 点击一个按钮
  2. 给矩形涂上红色
  3. 等待1秒
  4. 将矩形涂成蓝色

在下面的代码中:


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 处创建了一个宽度和高度为 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!走向世界!

但是我收到一个错误。为什么会这样?我不能修改 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)

最佳答案

这是因为任何 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组件或仅 Java FX成分,避免混合 SwingJavaFX组件,除非您别无选择。

关于Javafx 修改 SwingUtilities.invokeLater 中的 "Label",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39982845/

相关文章:

JavaFX - 无法从 FXML 文件加载节点

java - ObservableList:如何可靠地检测 setAll?

java - 最大化javafx后舞台最大化场景

sql-server - SQL Server Management Studio Pane 设置,始终显示图表 Pane 、条件 Pane 和 SQL Pane

java - 如何从 AsyncTask 扩展为通用基类?

JavaFX 8,带复选框的 ListView

java - 在 SlidingPaneLayout 实现中 Pane 始终打开

java - 在 JavaFX 中调整窗口大小时动态调整图形大小

java - 让Struts为不同的角色显示不同的JSP

java - 测试 Lucene Query 是否匹配所有文档