簡體   English   中英

Java Swing Timer:文本未更新

[英]java swing timer: texts not updating

這是我第一次使用Java Swing計時器。 我的目標是每秒更新一次標簽,但是當我運行該程序時,會出現錯誤。 為了確保它只帶有標簽的錯誤,我嘗試插入一個進度條,該進度條應該慢慢填充,然后才起作用。 我應該怎么辦?

這是我的主要課程:

package Application;

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class main extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        Parent root =   FXMLLoader.load(getClass().getResource("/Interface/interface.fxml"));
        Scene scene = new Scene (root);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

這是我的fxml文檔的主要控制器:

package Application;

import java.awt.event.ActionListener;
import java.net.URL;
import java.util.ResourceBundle;

import javax.swing.Timer;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;

public class MainController implements Initializable {

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        // TODO Auto-generated method stub

    }

    @FXML
    Label label;
    double count = 0.0;

    public void ok(ActionEvent event){
        ActionListener action = new ActionListener(){

            @Override
            public void actionPerformed(java.awt.event.ActionEvent arg0) {
                count+=0.1;
                label.setText(count+"");
            }
        };

        Timer timer = new Timer(1000, action);
        timer.start();
    }
}

這就對了。 我有一個應該啟動計時器“ timer”的按鈕,該按鈕應該更改標簽“ label”。 方法“ ok”是按下按鈕時調用的方法。 而且,正如我已經說過的,它應該啟動計時器。 但是當我這樣做時,我得到一個錯誤:

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:236)
    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 Application.MainController$1.actionPerformed(MainController.java:46)
    at javax.swing.Timer.fireActionPerformed(Unknown Source)
    at javax.swing.Timer$DoPostEvent.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$500(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

我能做什么?

與Swing相似,有一個特殊的線程需要運行“內部”來進行UI更新-Java FX事件分配線程,該線程處理所有與GUI相關的任務。

您需要在此處使用Platform.runLater()

換句話說:您需要定義一個進行更新的Runnable 然后將該Runnable的實例傳遞給上述runLater()

您的錯誤消息基本上是在告訴您FX不希望您在任何其他線程中進行更新!

此外:它不應該直接相關,但是最好使用java.util.Timer而不是java.Swing.Timer

編輯:您需要這樣的事情 假設您希望事情由ok()方法觸發:

public void ok(ActionEvent event){
    final Runnable update = new Runnable() {
       @Override 
       public void run() {
         count+=0.1;
         label.setText(count+"");
        }
    };

   ActionListener delayedAction = new ActionListener(){
     @Override
     public void actionPerformed(java.awt.event.ActionEvent arg0) {
       Platform.runLater(update);
     }
   };

   new Timer(1000, delayedAction).start();
}

    Platform.runLater(update);
}

上面做了:

A)創建一個Runnable對象,該對象將更新您的UI元素

B)使用“已知的” Swing Timer通過所需的Platform.runLater()調用來調用該Runnable

那應該可以,但是可能需要進行一些微調(代碼既未編譯也未測試)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM