2016-12-03 6 views
1

Ich habe versucht, einen Timer mit JavaFX mit Scenebuilder zu erstellen, aber ich habe einige Probleme mit dem Erstellen von Threads. Immer wenn ich den Startknopf drücke, bleibt die Anwendung zurück und aktualisiert den Text nie wirklich. Ich habe versucht, Platform.runLater() zu verwenden, aber wie oben erwähnt, bleibt alles zurück und als Ergebnis.JavaFX Timer Thread Probleme

Hier sind die Methoden, um die Timer-Steuerung auf bestimmte Tasten auf der FXML Datei verknüpft:

@FXML 
private void startTimer(){ 
    System.out.println("started"); 
    stopWatch.startTimer(); 

} 

@FXML 
private void pauseTimer(){ 
    stopWatch.pauseTimer(); 
} 

@FXML 
private void stopTimer(){ 
    System.out.println("stopped"); 
    stopWatch.stopTimer(); 
} 

@FXML 
public void updateTimer(long dT){ 

    //System.out.println(((dT/6000)%1000)+":"+String.valueOf((dT/1000)%1000)+","+String.valueOf((dT)%1000)); 
    Platform.runLater(() ->{ 
     timer.setText(String.valueOf(dT/1000)); 
    }); 
} 

Und hier ist die StopWatch.java Klasse:

package sled.timer.address.model; 

import sled.timer.address.view.PersonOverviewController; 

public class StopWatch implements Runnable{ 

private Thread runThread; 
public boolean running = false; 
public boolean paused = false; 


private long summedTime = 0; 

PersonOverviewController personOverviewController; 

String time = ""; 

public void count(){ 

} 
public StopWatch(PersonOverviewController personOverviewController){ 
    this.personOverviewController = personOverviewController; 

} 
public void startTimer(){ 
    running = true; 
    paused = false; 

    runThread = new Thread(this); 
    runThread.start(); 
} 

public void pauseTimer(){ 
    paused = true; 
} 

public void stopTimer(){ 
    running = false; 
    paused = false; 
} 
@Override 
public void run() { 
    // TODO Auto-generated method stub 
    long startTime = System.currentTimeMillis(); 
    while(running && !paused){ 
     personOverviewController.updateTimer(summedTime + (System.currentTimeMillis() - startTime)); 
    } 
    if(paused) 
     summedTime += System.currentTimeMillis() - startTime; 

    else 
     summedTime = 0; 

} 

public long getSummedTime(){ 
    return summedTime; 
} 

Jede Hilfe sehr geschätzt wird.

Antwort

0

Sie beschränken nicht die Aktualisierungshäufigkeit Ihres Threads. Auf diese Weise können Sie so viele Runable s für den Anwendungsthread ausführen, dass es wenig Zeit für die Ereignisbehandlung und das Layout gibt, die Ihre Anwendung so verhalten.

Außerdem synchronisieren Sie die Zugriffe auf die booleschen Flags nicht und machen sie nicht volatile, was bedeutet, dass Wertänderungen nicht für andere Threads sichtbar werden.

Stattdessen sollten Sie sicherstellen, dass kein Updates mehr veröffentlicht werden, bis die letzten Runnable gestartet wurde:

private final Object updaterLock = new Object(); 
private final boolean updating = false; 
private final long value; 

public void updateTimer(long dT) { 
    synchronized (updaterLock) { 
     value = dT; 
     if (!updating) { 
      updating = true; 
      Platform.runLater(() -> { 
       synchronized (updaterLock) { 
        updating = false; 
        timer.setText(Long.toString(value/1000)); 
       } 
      }); 
     } 
    } 
} 
public class StopWatch implements Runnable{ 

    ... 

    public volatile boolean running = false; 
    public volatile boolean paused = false; 

jedoch the AnimationTimer class prüfen, mit dem Updates zu tun. Die Aktualisierungshäufigkeit dieser Klasse ist begrenzt.