我尽量避免寻求帮助,尽我所能。但是我一直在研究这个问题太久了。我甚至不明白出了什么问题。哦,当我尝试测试它时,我的GUI冻结
我必须做一个基本的秒表:开始,停止,恢复和重置。但我无法做到。如果您还要评论或解释您的代码,请,因为我感到无能为力。 (我的一些评论是过去的代码,我认为它可以工作,但没有)
package gameclock;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class GameClock extends Application {
public void start(Stage primaryStage) {
HBox pane = new HBox();
Scene scene = new Scene(pane, 400, 100);
Button start = new Button("Start");
Button stop = new Button("Stop");
Button resume = new Button("Resume");
Button reset = new Button("Reset");
final TextField display = new TextField("0");
display.setEditable(false);
boolean onOff = false;
DateFormat df = new SimpleDateFormat("ss");
Calendar calobj = Calendar.getInstance();
System.out.println(df.format(calobj.getTime()));
start.setOnAction((ActionEvent event) ->
{
int time = Integer.parseInt(display.getText());
/*
Timer t = new Timer();
final int time1 = 1;
t.scheduleAtFixedRate(new TimerTask()
{
public void run()
{
time = time1 + 1;
}
},0,0);
display.setText(String.valueOf(time1));
*/
long timestamp = System.currentTimeMillis(); //divide by 1000 cause a millisecond is 1000 of a second
while (!onOff)
{
if(System.currentTimeMillis() - timestamp > 1000)
{
time++;
display.setText(String.valueOf(time));
}
}
String time2String = Long.toString(timestamp);
});
stop.setOnAction((ActionEvent event) ->
{
if(onOff == false)
onOff(true);
});
resume.setOnAction((ActionEvent event) ->
{
onOff(true);
});
pane.getChildren().addAll(start, display, resume, stop, reset);
pane.setAlignment(Pos.CENTER);
pane.setPadding(new Insets(0, 0, 0, 0));
primaryStage.setTitle("Stop Watch");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
private void onOff(boolean b) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
答案 0 :(得分:2)
您通过将循环直接添加到事件处理程序来阻止应用程序线程。这导致UI未被更新,并且不会处理其他事件。
最好使用AnimationTimer
:
AnimationTimer timer = new AnimationTimer() {
private long timestamp;
private long time = 0;
private long fraction = 0;
@Override
public void start() {
// current time adjusted by remaining time from last run
timestamp = System.currentTimeMillis() - fraction;
super.start();
}
@Override
public void stop() {
super.stop();
// save leftover time not handled with the last update
fraction = System.currentTimeMillis() - timestamp;
}
@Override
public void handle(long now) {
long newTime = System.currentTimeMillis();
if (timestamp + 1000 <= newTime) {
long deltaT = (newTime - timestamp) / 1000;
time += deltaT;
timestamp += 1000 * deltaT;
display.setText(Long.toString(time));
}
}
};
这将在每一帧的应用程序线程上运行handle
方法。
您可以使用start()
和stop()
来启动和停止秒表。
答案 1 :(得分:0)
我能识别出最好的无限循环:
while (!onOff)
{
if(System.currentTimeMillis() - timestamp > 1000)
{
time++;
display.setText(String.valueOf(time));
}
}
我不像Java / Android那样了解JavaFX,但是在那个循环中没有什么可以将onOff
从false转换为true。即使你有另一个按钮回调来将onOff
切换为true,它也不会被调用,因为你的UI线程停留在上面的循环中以进行启动按钮操作。
更新
现在我看到你要做的事情:用当前时间更新文本值,你想要使用的是计时器的概念。计时器是一种UI概念,您将在以后回调,同时仍然允许您的UI响应。快速google&#34; JavaFX计时器&#34;揭示了如何做到这一点的很多点击。