这是我第一次使用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();
}
}
就是这样。我有一个按钮,应该启动定时器“定时器”,它应该更改标签“标签”。方法“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)
我该怎么办?
答案 0 :(得分:3)
与Swing类似,您需要运行特殊主题"内部"进行UI更新 - Java FX事件调度线程,它处理所有与GUI相关的任务。
您需要在此处使用Platform.runLater()
。
换句话说:您需要定义进行更新的 Runnable
;然后将Runnable
的实例传递给前面提到的runLater()
。
您的错误消息基本上告诉您FX并不希望您在任何其他线程中进行更新!
此外:它不应该直接重要,但可能最好使用java.util.Timer
代替java.Swing.Timer
。
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)创建一个将更新UI元素的Runnable对象
B)使用"已知" Swing Timer使用所需的Platform.runLater()调用调用 Runnable
这应该可行,但可能需要一些微调(代码既不编译也不测试)。