[英]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.