2016-07-30 17 views
-1

ich versuche, mehrere Countdown-Timer gleichzeitig mit javafx auszuführen. derzeit verwendetes Multithreading. Jetzt versuche ich, die Timer in Etiketten zu drucken, um auf dem Bildschirm angezeigt zu werden, jedoch nicht in der Lage, dies zu tun, weil ich nicht auf die Controller-Klasse zugreifen kann, um sie zu drucken. Wie erreiche ich das Drucken des Timer-Wertes auf Etiketten mit meiner Thread-Klasse. Mein Timer-Wert sollte in Etiketten in einer Gridpanel gedruckt werden, so dass ich die Einschränkungen von der Controller-Klasse erhalten und dann entsprechend drucken.JavaFX Multithreading und Controller-Klasse

package tabapplication; 
import java.util.Timer; 
import java.util.TimerTask; 
import tabapplication.TabApplication; 
import tabapplication.FXMLDocumentController; 
class Rdt implements Runnable { 
    private Thread t; 
    private String threadName; 

    Rdt(String name){ 
     threadName = name; 
     System.out.println("Creating " + threadName); 
    } 
    public void run() { 
     System.out.println("Running " + threadName); 
     try { 
      final Timer timer = new Timer(); 
     timer.scheduleAtFixedRate(new TimerTask() { 
      int s = 60; 
      int m=30; 
      public void run() { 
       s--; 
       if(s<0 && m>0) 
       {m--; 
       s=59; 
       } 
       if(s<10) 
       { System.out.println(Integer.toString(m)+":"+0+Integer.toString(s)); } 
       else 
       {System.out.println(Integer.toString(m)+":"+Integer.toString(s));} 


       if(m==0 && s==0) 
        timer.cancel(); 
      } 
     }, 0, 10); 
      Thread.sleep(50); 
    } catch (InterruptedException e) { 
     System.out.println("Thread " + threadName + " interrupted."); 
    } 
    System.out.println("Thread " + threadName + " exiting."); 
    } 

    public void start() 
    { 
     System.out.println("Starting " + threadName); 
     if (t == null) 
     { 
     t = new Thread (this, threadName); 
     t.start(); 
     } 
    } 
    public static void main(String args[]) { 

     Rdt R1 = new Rdt("Thread-1"); 
     Thread obj1=new Thread(R1); 
     obj1.start(); 

     Rdt R2 = new Rdt("Thread-2"); 
    Thread obj2=new Thread(R2); 
    obj2.start(); 
    } 
} 
+0

„Ich kann die Controller-Klasse zugreifen ... ". Warum nicht? Vermutlich würden Sie in Ihrer JavaFX-Anwendung diese Timer * von * dem Controller instantiieren (z. B. als Reaktion auf eine Benutzeraktion). –

+0

Ich möchte, dass die Timer unabhängig und gleichzeitig laufen, aber in meinem Fall ist nur ein Mal läuft und andere stoppt. Deshalb verwende ich Thread für verschiedene Timer. Vom fxml-Controller aus rufe ich den oben erwähnten Java-Code auf. aber ich muss jeden Timer an einer bestimmten Position in einem Raster platzieren. Nicht in der Lage das zu erreichen. –

Antwort

1

Geben Sie Ihre Rdt ein Callback-Klasse auszuführen, wenn die Zeit es Änderungen darstellt. Dies könnte in Form eines Consumer<String> zum Beispiel sein:

class Rdt implements Runnable { 
    private Thread t; 
    private String threadName; 

    private Consumer<String> callback ; 

    Rdt(String name, Consumer<String> callback){ 
     threadName = name; 
     System.out.println("Creating " + threadName); 
     this.callback = callback ; 
    } 
    public void run() { 
     System.out.println("Running " + threadName); 
     try { 
      final Timer timer = new Timer(); 
     timer.scheduleAtFixedRate(new TimerTask() { 
      int s = 60; 
      int m=30; 
      public void run() { 
       s--; 
       if(s<0 && m>0) 
       {m--; 
       s=59; 
       } 
       if(s<10) 
       { callback.accept(Integer.toString(m)+":"+0+Integer.toString(s)); } 
       else 
       {callback.accept(Integer.toString(m)+":"+Integer.toString(s));} 


       if(m==0 && s==0) 
        timer.cancel(); 
      } 
     }, 0, 10); 
      Thread.sleep(50); 
    } catch (InterruptedException e) { 
     System.out.println("Thread " + threadName + " interrupted."); 
    } 
    System.out.println("Thread " + threadName + " exiting."); 
    } 

    // ... 
} 

nun von Ihrem Controller-Klasse können Sie einfach den Timer starten mit:

public class Controller { 

    @FXML 
    private Label timerLabel ; 

    @FXML 
    private void startTimer() { 
     Rdt timer = new Rdt("Timer-1", timerLabel::setText); 
     timer.run(); 
    } 
} 

Ein paar Randbemerkungen:

  1. Hier müssen keine Threads erstellt werden. Die Timer Klasse bereits erstellt einen Hintergrundthread für Sie, so dass dies in einem Hintergrundthread ausgeführt wird, ohne explizit einen zu erstellen.
  2. Sie erfinden das Rad an vielen Stellen neu. Die Standardbibliotheken haben z. B. bereits eine Duration class, die zur Darstellung von Minuten und Sekunden verwendet werden kann und die bereits die gesamte Arithmetik für Sie implementiert. Bedenken Sie:

    public class Rdt { 
    
        private String name ; 
    
        private Consumer<Duration> callback ; 
    
        private Duration time ; 
    
        public Rdt(String name, Consumer<Duration> callback) { 
         this.name = name ; 
         this.callback = callback ; 
        } 
    
        public void startTimer() { 
         Timer timer = new Timer(); 
         time = Duration.ofMinutes(30); 
         timer.scheduleAtFixedRate(new TimerTask() { 
          @Override 
          public void run() { 
           time = time.minusSeconds(1); 
           callback.accept(time); 
           if (time.isZero()) { 
            timer.cancel(); 
           } 
          } 
         }, 0, 10); 
        } 
    } 
    

und in ähnlicher Weise weiß die DateTimeFormatter Klasse, wie die Zeiten als Strings schön zu formatieren, so von der Steuerung würden Sie tun:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("mm:ss"); 
Rdt timer = new Rdt("Timer-1", time -> timerLabel.setText(formatter.format(time))); 
timer.start(); 
+0

Wenn das Etikett, wo ich die Zeit drucken möchte, in einem Rasterbereich ist, was tue ich, um es dort zu drucken. Zurzeit wurde das Gridpanel mit dem Szenengenerator erstellt, so dass es in der fxml-Datei vorhanden ist. Ich habe die Zeit durch meine Controller-Klasse gedruckt. Ansatz war Rdt Klasse für verschiedene Instanzen von Timer aufrufen und Rückgabewerte an Controller-Klasse, um es in der Bezeichnung zu drucken, die ich nicht erreichen kann. Könnten Sie Änderungen oder alternative Maßnahmen vorschlagen, um das Gleiche zu tun? @James_D –

+0

Privatverbraucher Rückruf; generationg error kann in der Klasse Rdt kein Symbol finden –

+0

Fr. der erste Kommentar, die Antwort zeigt explizit, wie man das macht. Nicht sicher, was du vermisst. Für die zweite, haben Sie die Importe aufgenommen? –