2017-12-07 9 views
0

私は現在、時間を基数10に変換するプロジェクトに取り組んでいます(基本的に、渡された日のパーセンテージを表示するようになります)。例:12:00正午は次のように表示されます。ベース10時間で50.00)。現在のところ、コンソールに印刷すると正しく出力されるため、アルゴリズムが正しいことがわかりますが、何らかの理由でGUIを表示できません。正しい番号を表示するためにGUIを常に更新しようとする部分を取り除くと、GUIはうまく表示されますが、数字は表示されません。私のコードは次のとおりです。JavaFX GUIを絶え間なく更新しています

package ClockPackage; 

import java.util.Calendar; 
import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.layout.Pane; 
import javafx.scene.text.Text; 
import javafx.stage.Stage; 

public class ClockView extends Application { 
    Pane background; 
    static Text firstDigit; 
    static Text secondDigit; 
    static Text thirdDigit; 
    static Text fourthDigit; 
    Text middleDecimal; 

    /* Sets the first digit of the base 10 time to the passed through char. */ 
    static void setFirstDigit(char x1) { 
     String digitString = ""; 
     digitString += x1; 
     firstDigit.setText(digitString); 
    } 

    /* Sets the second digit of the base 10 time to the passed through char. */ 
    static void setSecondDigit(char x2) { 
     String digitString = ""; 
     digitString += x2; 
     secondDigit.setText(digitString); 
    } 

    /* Sets the third digit of the base 10 time to the passed through char. */ 
    static void setThirdDigit(char y1) { 
     String digitString = ""; 
     digitString += y1; 
     thirdDigit.setText(digitString); 
    } 

    /* Sets the fourth digit of the base 10 time to the passed through char. */ 
    static void setFourthDigit(char y2) { 
     String digitString = ""; 
     digitString += y2; 
     fourthDigit.setText(digitString); 
    } 

    /* Main Method that Launches the GUI */ 
    public static void main(String[] args) { 
     Application.launch(args); 

    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
      final double TEXTFIELD_LAYOUT_Y = 200; 

      //Background Pane 
      background = new Pane(); 

      //First digit textField 
      firstDigit = new Text(); 
      firstDigit.setLayoutX(17); 
      firstDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
      firstDigit.setStyle("-fx-font-size: 96pt;"); 

      //Second digit textField 
      secondDigit = new Text(); 
      secondDigit.setLayoutX(117); 
      secondDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
      secondDigit.setStyle("-fx-font-size: 96pt;"); 

      //Middle decimal 
      middleDecimal = new Text("."); 
      middleDecimal.setLayoutX(219); 
      middleDecimal.setLayoutY(210); 
      middleDecimal.setStyle("-fx-font-size: 72pt;"); 

      //Third digit textField 
      thirdDigit = new Text(); 
      thirdDigit.setLayoutX(250); 
      thirdDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
      thirdDigit.setStyle("-fx-font-size: 96pt;"); 

      //Fourth digit textField 
      fourthDigit = new Text(); 
      fourthDigit.setLayoutX(362); 
      fourthDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
      fourthDigit.setStyle("-fx-font-size: 96pt;"); 

      /* Adding the Nodes to the Pane */ 
      background.getChildren().addAll(firstDigit, secondDigit, middleDecimal, thirdDigit, fourthDigit); 

      /* Setting the Scene */ 
      Scene scene = new Scene(background, 470, 258); 
      primaryStage.setTitle("Base 10 Clock"); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 

      /* 
      * Calculates the time in base 10 time and calls the 4 methods 
      * to set the GUI display. 
      * 
      * In a constant while loop in order to continuously update 
      * the GUI. 
      */ 
      Calendar now; 
      double currentTime; 
      String timeString; 
      long timestamp; 
      while(true) { 
       /* Sleep for 8.64 seconds since that is how long it is between 
       increments of 0.01 in base 10 time. */ 
       Thread.sleep(8640); 
       now = Calendar.getInstance(); 
       timestamp = now.get(Calendar.HOUR_OF_DAY)*60*60 + now.get(Calendar.MINUTE)*60 + now.get(Calendar.SECOND); 
       currentTime = timestamp/86400.0; 
       timeString = "" + currentTime; 
       setFirstDigit(timeString.charAt(2)); 
       setSecondDigit(timeString.charAt(3)); 
       setThirdDigit(timeString.charAt(4)); 
       setFourthDigit(timeString.charAt(5)); 
      } 
    } 
} 

誰もが、私は両方が現れ、常に数字を更新GUIを作って行くだろうか任意のアイデアを持っていますか?私はそれが両方をする方法を理解できません。私は人々がボタンを使ってデータを更新する場所を見てきましたが、ディスプレイが常に自動的に更新される場所は見ていません。

ありがとうございます!

+2

'while(true)' - <これはGUIスレッドの 'JavaFX'プログラムでは絶対しないでください。 [AnimationTimer](https://docs.oracle.com/javase/8/javafx/api/javafx/animation/AnimationTimer.html)クラスを使用します。 – Sedrick

+0

[タイムライン](https://docs.oracle.com/javase/8/javafx/api/javafx/animation/Timeline.html)がこれに適しています。 – Sedrick

答えて

0

ここには有効なバージョンがあります。

import java.util.Calendar; 
import java.util.Timer; 
import java.util.TimerTask; 

import javafx.application.Application; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.layout.Pane; 
import javafx.scene.text.Text; 
import javafx.stage.Stage; 

public class ClockView extends Application { 
    Pane background; 
    static Text firstDigit; 
    static Text secondDigit; 
    static Text thirdDigit; 
    static Text fourthDigit; 
    Text middleDecimal; 

    public final Timer clockTimer = new Timer(); 


    /* Sets the first digit of the base 10 time to the passed through char. */ 
    static void setFirstDigit(char x1) { 
     String digitString = ""; 
     digitString += x1; 
     firstDigit.setText(digitString); 
    } 

    /* Sets the second digit of the base 10 time to the passed through char. */ 
    static void setSecondDigit(char x2) { 
     String digitString = ""; 
     digitString += x2; 
     secondDigit.setText(digitString); 
    } 

    /* Sets the third digit of the base 10 time to the passed through char. */ 
    static void setThirdDigit(char y1) { 
     String digitString = ""; 
     digitString += y1; 
     thirdDigit.setText(digitString); 
    } 

    /* Sets the fourth digit of the base 10 time to the passed through char. */ 
    static void setFourthDigit(char y2) { 
     String digitString = ""; 
     digitString += y2; 
     fourthDigit.setText(digitString); 
    } 

    /* Main Method that Launches the GUI */ 
    public static void main(String[] args) { 
     launch(args); 
    } 


    @Override 
    public void start(Stage primaryStage) throws Exception { 
     final double TEXTFIELD_LAYOUT_Y = 200; 

     //Background Pane 
     background = new Pane(); 

     //First digit textField 
     firstDigit = new Text("0"); 
     firstDigit.setLayoutX(17); 
     firstDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
     firstDigit.setStyle("-fx-font-size: 96pt;"); 

     //Second digit textField 
     secondDigit = new Text("0"); 
     secondDigit.setLayoutX(117); 
     secondDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
     secondDigit.setStyle("-fx-font-size: 96pt;"); 

     //Middle decimal 
     middleDecimal = new Text("."); 
     middleDecimal.setLayoutX(219); 
     middleDecimal.setLayoutY(210); 
     middleDecimal.setStyle("-fx-font-size: 72pt;"); 

     //Third digit textField 
     thirdDigit = new Text("0"); 
     thirdDigit.setLayoutX(250); 
     thirdDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
     thirdDigit.setStyle("-fx-font-size: 96pt;"); 

     //Fourth digit textField 
     fourthDigit = new Text("0"); 
     fourthDigit.setLayoutX(362); 
     fourthDigit.setLayoutY(TEXTFIELD_LAYOUT_Y); 
     fourthDigit.setStyle("-fx-font-size: 96pt;"); 

     /* Adding the Nodes to the Pane */ 
     background.getChildren().addAll(firstDigit, secondDigit, middleDecimal, thirdDigit, fourthDigit); 

     /* Setting the Scene */ 
     Scene scene = new Scene(new Group(), 470, 258); 
     Group root = (Group)scene.getRoot(); 
     root.getChildren().add(background); 
     primaryStage.setTitle("Base 10 Clock"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     clockTimer.scheduleAtFixedRate(new TimerTask() { 

       Calendar now; 
       double currentTime; 
       String timeString; 
       long timestamp; 

       @Override 
       public void run() { 
        /* 
        * Calculates the time in base 10 time and calls the 4 methods 
        * to set the GUI display. 
        * 
        * In a constant while loop in order to continuously update 
        * the GUI. 
        */ 
        now = Calendar.getInstance(); 
        timestamp = now.get(Calendar.HOUR_OF_DAY)*60*60 + now.get(Calendar.MINUTE)*60 + now.get(Calendar.SECOND); 
        currentTime = timestamp/86400.0; 
        timeString = "" + currentTime; 
        Platform.runLater(new Runnable() { 
         @Override public void run() { 
          setFirstDigit(timeString.charAt(2)); 
          setSecondDigit(timeString.charAt(3)); 
          setThirdDigit(timeString.charAt(4)); 
          setFourthDigit(timeString.charAt(5)); 
         } 
        }); 
       } 
      }, 0, 8640 // Sleep for 8.64 seconds since that is how long it is between 
     );    // increments of 0.01 in base 10 time. 
    } 
} 
+2

これは良くありません。これによりJavaFXアプリケーションスレッドのシーングラフが変更され、競合状態(https://en.wikipedia.org/wiki/Race_condition)が発生する可能性があります。 ['Platform.runLater'](https://docs.oracle.com/javase/8/javafx/api/javafx/application/Platform.html#runLater-java.lang.Runnable-)を適切に使用すると、これを修正できます。 – jewelsea

+0

@jewelsea guiのアップデートを変更して、Platform.runLaterを使用するようにしました。より良いMVCデザインが役立ちます。提案していただきありがとうございます。 –

2

置き換えますと

Calendar now; 
    double currentTime; 
    String timeString; 
    long timestamp; 
    while (true) 
    { 
     /* Sleep for 8.64 seconds since that is how long it is between 
      increments of 0.01 in base 10 time. */ 
     Thread.sleep(8640); 
     now = Calendar.getInstance(); 
     timestamp = now.get(Calendar.HOUR_OF_DAY) * 60 * 60 + now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND); 
     currentTime = timestamp/86400.0; 
     timeString = "" + currentTime; 
     setFirstDigit(timeString.charAt(2)); 
     setSecondDigit(timeString.charAt(3)); 
     setThirdDigit(timeString.charAt(4)); 
     setFourthDigit(timeString.charAt(5)); 
    } 

 Timeline overEightSeconsWonder = new Timeline(new KeyFrame(Duration.seconds(8.64), (ActionEvent event) -> 
     { 
      Calendar now = Calendar.getInstance(); 
      long timestamp = now.get(Calendar.HOUR_OF_DAY) * 60 * 60 + now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND); 
      double currentTime = timestamp/86400.0; 
      String timeString = "" + currentTime; 
      setFirstDigit(timeString.charAt(2)); 
      setSecondDigit(timeString.charAt(3)); 
      setThirdDigit(timeString.charAt(4)); 
      setFourthDigit(timeString.charAt(5)); 
     })); 
     overEightSeconsWonder.setCycleCount(Timeline.INDEFINITE); 
     overEightSeconsWonder.play(); 
0

をあなたは新しいスレッドまたは他のスレッドを持つサービスコールでwhile(true)ループを交換する必要があります。メインスレッドは既にUIの更新を担当しているので、何らかの種類のブロック(IO、長い時間がかかるループなど)があると、UIスレッドの更新が妨げられます。

Link to the Service interface

サービスの作成:あなたのコントローラに続いて

public static class TimeService extends Service<String> { 

    protected Task createTask() { 
     return new Task<String>() { 
      protected String call() throws Exception { 
       // TODO: Do work - return the date/time as a String 
       // If you need a Thread.sleep, use a spawn a new thread 
      } 
     }; 
    } 
} 

を:

TimeService timeService = new TimeService(); 
timeService.restart(); 

ます。また、(TimeServiceのプロパティにUI要素を結合のようなもののすべてのソートを行うことができますサービスが実行されている間、UIは「ちょうど更新」されます)。

関連する問題