JavaFX多线程和控制器类

时间:2016-07-30 23:19:13

标签: java multithreading controller javafx-8

我正在尝试使用javafx同时执行多个倒计时器。目前使用多线程。现在我试图在标签上打印定时器,以便在屏幕上显示,但无法这样做因为我无法访问控制器类来打印它。如何使用我的线程类在标签上实现打印计时器值。我的计时器值应该打印在gridpane中的标签中,所以我从控制器类中获取约束,然后相应地打印。

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();
   }   
}

1 个答案:

答案 0 :(得分:1)

Rdt类提供一个回调函数,以便在它代表更改时执行。这可以是Consumer<String>的形式,例如:

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.");
   }

   // ...
}

现在,您可以从控制器类中启动计时器:

public class Controller {

    @FXML
    private Label timerLabel ;

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

一些旁白:

  1. 此处无需创建线程。 Timer已经为您创建了一个后台线程,因此这将在后台线程中运行,而不会显式创建一个。
  2. 你真的在很多地方重新发明轮子。例如,标准库已经有一个Duration class,它可以用来表示分钟和秒,并且已经为你实现了所有的算术运算。考虑:

    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);
        }
    }
    
  3. 同样地,DateTimeFormatter类知道如何将时间格式化为字符串,所以从控制器中你可以做到:

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