创建简单的秒表 - javaFX

时间:2016-11-26 18:49:15

标签: java user-interface javafx

我尽量避免寻求帮助,尽我所能。但是我一直在研究这个问题太久了。我甚至不明白出了什么问题。哦,当我尝试测试它时,我的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.
}

}

2 个答案:

答案 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;揭示了如何做到这一点的很多点击。