2016-11-26 36 views
0

我儘量避免尋求幫助,盡我所能做我自己。但是我一直在研究這個問題太久了。我什至不明白什麼是錯的。哦,當我嘗試測試它時,我的GUI凍結創建簡單的秒錶 - javaFX

我必須做一個基本的秒錶:開始,停止,恢復和重置。但我無法做到。如果您還要評論或解釋您的代碼,請因爲我感到無能爲力。 (我的一些意見是過去的代碼,我以爲會工作,但沒有)

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

,我認得出他們最好的無限循環:

​​

我不對JavaFX和Java/Android都不太瞭解,但是沒有什麼能夠在該循環中將onOff從false切換到true。即使您有另一個按鈕回調將onOff切換爲true,它也不會被調用,因爲您的UI線程停留在上面的循環中以用於啓動按鈕操作。

更新:

現在,我看你想做什麼:更新與當前時間的文本值,你要使用什麼是計時器的概念。計時器是一種UI概念,您可以在將來回調您的UI,同時讓您的UI響應。 「JavaFX計時器」的快速谷歌揭示瞭如何做到這一點點擊。

+0

我知道循環是無止境的。我是這樣設計的。我希望它能夠在按下停止按鈕時將其從循環中取出。 –

+0

這是問題所在。您的按鈕回調發生在您的應用程序的主線程上 - 由在調用堆棧底部的循環中運行的調度事件處理程序發出。如果您的按鈕事件處理程序未返回,則其他事件處理程序將無法運行。因此,您的UI線程在無限循環中凍結並且變得無響應。你想要做的是看到我關於UI定時器的更新答案。只要做一個互聯網搜索「Java定時器」或「JavaFX定時器」。你可能只需要一個計時器事件來每隔1秒觸發一次,你是否可以更新屏幕上的文本。 – selbie

0

您正在通過將循環直接添加到事件處理程序來阻止應用程序線程。這導致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()來啓動和停止秒錶。